fatherOfWine fatherOfWine - 2 months ago 57
C# Question

JSON.NET JsonConvert.SerializeObject() peculiar behavior

Here is my situation. We are at the junction to decide what Json serialization tool to use. we are considering Newtonsoft.JSON and Microsoft JavaScriptSerializer. Newtonsoft.JSON has been our first peek, but we stumble over peculiar behaviour. Here is schematic code to ilustrate the problem.
Let say we have following disposition of classes:

interface IA<T>
{
T Id { get; set; }
}

[DataContractAttribute]
abstract class A : IA<string>
{
protected A() { }

[DataMemberAttribute]
public virtual string Id
{
get;
set;
}
}
class B : A
{
public string P1 { get; set; }
public string P2 { get; set; }
}


Then if we will utilize Newtonsoft.Json's JsonConvert class to get JSON string out of the B class we could use following code:

B b = new B();
string jsonOutput = Newtonsoft.Json.JsonConvert.SerializeObject(b,
new Newtonsoft.Json.JsonSerializerSettings() {
NullValueHandling = Newtonsoft.Json.NullValueHandling.Include
});


But unfortunately only Id property would be reflected in the resulting JSON string. All other properties of the B class would not show up. Contrary, JavaScriptSerializer produces JSON string as expected though. Class B is our class, class A and interface IA are from 3rd party library so we could not modify them. Also we don't want to use data contract serialization annotation on our classes either just to appease picky json serializer.

Is there any way to instruct Newtonsoft.Json.JsonConvert to serialize all properties regardless annotated or not?

EDIT: Though @LB provided acceptable answer @dbc came up with more comprehensive solution, so if you wanna see it just following to the link he provided as duplication for this question.

L.B L.B
Answer

You don't need DataContractAttributeand DataMemberAttributefor Json.Net . Remove them and your code will work....

Either use them for all properties or never use them

See http://www.newtonsoft.com/json/help/html/DataContractAndDataMember.htm

------ EDIT-------

If you don't wan't to use any Attributes then you can create a custom ContractResolver

public class MyDefaultContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var result = base.CreateProperties(type, memberSerialization).ToList();
        result.ForEach(x => { x.Ignored = false; }); // <-- Include or not? 
        return result;
    }
}

And serialize your code as:

string jsonOutput = Newtonsoft.Json.JsonConvert.SerializeObject(b,
new Newtonsoft.Json.JsonSerializerSettings()
{
    NullValueHandling = Newtonsoft.Json.NullValueHandling.Include,
    ContractResolver = new MyDefaultContractResolver()
});
Comments