15

I met a situation as below could anybody help me achieve as below?

For Example, if I have the class:-

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

My Myclass will be as follow:

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

When I am using Json.net to Serialize the object of the class Sample,I got as below and it works well.

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

Its correct but I wonder is it possible to get the json string as below?

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

1 Answer 1

23

You can create anonymous object and serialize it:

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 
              });

Result

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

But I suggest you either use default serialization of your Sample class, or create class which will be serialized into your format (i.e. move MyClass properties into Sample).

UPDATE: You can use custom converter, which flattens object and serializes all inner objects properties as top level object properties:

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
    }
}

Usage:

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

Or you can simply hide anonymous type creation into custom converter, if you need this behavior for one type only:

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);
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your help buddy. Is there any way to do this using CustomConverters?
I think The above code will not be convenient when the property class has more number of properties.
Thanks buddy I will let you know after i check it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.