Объединить два объекта во время сериализации с помощью json.net?

Я встретил ситуацию, как внизу, может кто-нибудь помочь мне достичь, как показано ниже?

For Example:

У меня есть класс, как показано ниже,

public class Sample
{
    public String name{get;set;}
     public MyClass myclass{get;set;}
 }

My Myclass будет выглядеть следующим образом:

public class MyClass
{
    public String p1{get;set;}
     public String p2{get;set;}
 }

Когда я использую Json.net для сериализации объекта класса Sample, я получил как показано ниже, и он работает хорошо.

{
 "name":"...",
 "myclass":
          {
            "p1":"...",
            "p2":"..."
           }
 }

Правильно, но я сомневаюсь, что можно получить строку json, как показано ниже?

{
 "name":"...",
 "p1":"...",
 "p2":"..."
 }

Заранее спасибо

Мадху

Ответ 1

Вы можете создать анонимный объект и сериализовать его:

var sample = new Sample { 
    name = "Bob", 
    myclass = new MyClass { 
                p1 = "x", 
                p2 = "y" 
              }};

string json = JsonConvert.SerializeObject(new { 
                 sample.name, 
                 sample.myclass.p1, 
                 sample.myclass.p2 
              });

Результат

{"name":"Bob","p1":"x","p2":"y"}

Но я предлагаю вам либо использовать сериализацию по умолчанию вашего класса Sample, либо создать класс, который будет сериализован в ваш формат (т.е. переместить свойства MyClass в Sample).

UPDATE. Вы можете использовать настраиваемый конвертер, который выравнивает объект и сериализует все свойства внутренних объектов в качестве свойств объекта верхнего уровня:

public class FlattenJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, 
        JsonSerializer serializer)
    {
        JToken t = JToken.FromObject(value);
        if (t.Type != JTokenType.Object)
        {
            t.WriteTo(writer);
            return;
        }

        JObject o = (JObject)t;
        writer.WriteStartObject();
        WriteJson(writer, o);
        writer.WriteEndObject();
    }

    private void WriteJson(JsonWriter writer, JObject value)
    {
        foreach (var p in value.Properties())
        {
            if (p.Value is JObject)
                WriteJson(writer, (JObject)p.Value);
            else
                p.WriteTo(writer);
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, 
       object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType)
    {
        return true; // works for any type
    }
}

Использование:

string json = JsonConvert.SerializeObject(sample, new FlattenJsonConverter());

Или вы можете просто скрыть создание анонимного типа в пользовательский конвертер, если вам нужно это поведение только для одного типа:

public class SampleJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, 
        object value, JsonSerializer serializer)
    {
        Sample sample = (Sample)value;
        JToken t = JToken.FromObject(new { 
                      sample.name, 
                      sample.myclass.p1, 
                      sample.myclass.p2 
                   });

        t.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType,
        object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Sample);
    }
}