Member Serialization

Serialization at times throws curious situations that makes us look beyond the normal usages. Here is another situation that took sometime to find a solution for. Let’s examine the following code.

public class Test:BaseClass
{
  public string Name {get;set;}
}
[DataContract]
public class BaseClass
{
}

What would be the output if one was to serialize an instance of the Test class ?

var instance = new Test{Name="abc"};
var result = JsonConvert.SerializeObject(instance);

Let’s examine the output

{

}

Not surprising right ? After all the base class has been decorated with DataContractAttribute. This would ensure the only the members (or members of derieved classes) with DataMemberAttribute would be serialized.

As seen in the code above, while the base class doesn’t have any property, the child class has a single property (Name), which is NOT decorated with the mentioned attribute.
This is as per the design and works well in most cases. If one needs to be ensure the Child class members needs to be serialized, one needs to decorate it with the DataMemberAttribute.

public class Test:BaseClass
{
  [DataMember]
  public string Name {get;set;}
}
[DataContract]
public class BaseClass
{
}

This would ensure the Property Name is serialized.

{"Name":"abc"}

The other option he have is to remove the DataContractAttribute from the BaseClass, which would produce the same result.

But what if the Developer have following constrains
* Cannot access/change the BaseClass
* Should not use the DataMemberAttribute

The second constraint is chiefly driven by the factor that there are many Properties in the Child Class. This would require the developer to use the DataMemberAttribute on each of them, which is quite painful and naturally, one would want to avoid it.

The solution lies in a lesser known Property of the well known JsonObjectAttribute. The MemberSerialization.OptOut enumeratation ensures the following behavior.

All public members are serialized by default. Members can be excluded using JsonIgnoreAttribute or NonSerializedAttribute.

While this is the default member serialization mode, this gets overriden due the presence of ​DataContractAttribute` in the Parent Class.
Let’s modify our code again.

[JsonObject(MemberSerialization.OptOut)]
public class Test:BaseClass
{
  public string Name {get;set;}
}
[DataContract]
public class BaseClass
{
}

As seen the code above, the only change required would be decorated the Child Class with JsonObjectAttribute passing in the MemberSerialization.OptOut Enumeration for Member Serialization Mode.
This would produce the desired output

{"Name":"abc"}

Deserialize Json to Generic Type

One of the recent question in stackoverflow found interesting was about a Json, which needs to be deserialized to a Generic Class. What makes the question interesting was the Generic Property would have a different Json Property name depending on the type T. Consider the following Json

{
status: false,
employee:
{
firstName: "Test",
lastName: "Test_Last"
}
}

This needs to be Deseriliazed to the following class structures

public class Response<T>
{

[JsonProperty(PropertyName = "status")]
public bool Status {get;set;}

public T Item {get;set;}

}

[JsonObject(Title = "employee")]
public class Employee
{

[JsonProperty(PropertyName = "firstName")]
public string FirstName {get; set;}

[JsonProperty(PropertyName = "lastName")]
public string LastName {get; set;}

}

 

However, Response<T> being a generic class, would need to support additional Types as well. For example, the Json could also look like the following

{
status: false,
company:
{
companyname: "company name",
headquaters: "location"
}
}

Where the company needs to be deserialized to

[JsonObject(Title = "company")]
public class Employee {

[JsonProperty(PropertyName = "companyname")]
public string CompanyName {get; set;}

[JsonProperty(PropertyName = "headquaters")]
public string HeadQuaters {get; set;}

}

The solution lies in writing a Custom Contract Resolver, which does the magic. Let’s go ahead and write the ContractResolver.

public class GenericContractResolver<T> : DefaultContractResolver
{

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.UnderlyingName == nameof(Response<T>.Item))
{
foreach( var attribute in System.Attribute.GetCustomAttributes(typeof(T)))
{
if(attribute is JsonObjectAttribute jobject)
{
property.PropertyName = jobject.Title;
}
}
}
return property;
}
}

The role of the ContractResolver is pretty simple. As soon as it recognizes the Generic Type passed, it would replace the property name with the name described in JsonObjectAttribute.

Now you can use the ContractResolver to deserialize the Json. For example

var result = JsonConvert.DeserializeObject<Response<Employee>>(json,
new JsonSerializerSettings
{
ContractResolver = new GenericContractResolver<Employee>()
});

Demo Samples could be found here in my C# Fiddles

String or Array Converter : Json

Imagine you have a method which returns a Json String of following format.

{Name:'Anu Viswan',Languages:'CSharp'}

In order to deserialize the JSON, you could define a class as the following.

public class Student
{
public string Name{get;set;}
public string Languages{get;set;}
}

This work flawlessly. But imagine a situation when your method could return either a single Language as seen the example above, but it could additionally return a json which has multiple languages. Consider the following json

{Name:'Anu Viswan',Languages:['CSharp','Python']}

This might break your deserialization using the Student class. If you want to continue using Student Class with both scenarios, then you could make use of a Custom Convertor which would string to a collection. For example, consider the following Converter.

class SingleOrArrayConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(List<T>));
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
return token.ToObject<List<T>>();
}
return new List<T> { token.ToObject<T>() };
}

public override bool CanWrite
{
get { return false; }
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

 

Now, you could redefine your Student class as

public class Student
{
public string Name{get;set;}
[JsonConverter(typeof(SingleOrArrayConverter<string>))]
public List Languages{get;set;}
}

This would now work with both string and arrays.

Case 1 : Output

case 1

Case 2 : Output

case 2

Conditional Serialization using NewtonSoft Json

One of the least explored feature of Newtonsoft Json is the ability serialize properties conditionally. Consider the hypothetical situation wherein you want to serialize a property in a class only if a condition is satisfied. For example,

public class User
{
public string Name {get;set;}
public string Department {get;set;}
public bool IsActive {get;set;}
}

If the requirement is that you need to include serialize the Department Property only if the User Is Active, then the easiest way to do it would be to use the Conditional Serialization functionality of Json.Net. All you need to do is include a method that
a) Returns a boolean indicating whether to serialize or not.
b) Should be named with Property named prefixed with ‘ShouldSerialize’

For example, for the Property Department, the method should be named ‘ShouldSerializeDepartment’. Example,

public bool ShouldSerializeDepartment()=> IsActive;

Complete Code

public class User
{
public string Name {get;set;}
public string Department{get;set;}
public bool IsActive {get;set;}
public bool ShouldSerializeDepartment()=> IsActive;
}

Client Code

var user = new User{ Name = "Anu Viswan", IsActive = false} ;
var result = JsonConvert.SerializeObject(user);

Output

{"Name":"Anu Viswan","IsActive":false}

Serializing/Deserializing Dictionaries with Tuple as Key

Sometimes you run into things that might look trivial but it just do not work as expected. One such example is when you attempt to serialize/Deserialize a Dictionary with Tuples as the key. For example

var dictionary = new Dictionary<(string, string), int>
{
[("firstName1", "lastName1")] = 5,
[("firstName2", "lastName2")] = 5
};

var json = JsonConvert.SerializeObject(dictionary);
var result = JsonConvert.DeserializeObject<Dictionary<(string, string), string>>(json);

The above code would trow an JsonSerializationException when deserializing. But the good part is, the exception tells you exactly what needs to be done. You need to use an TypeConverter here.

Let’s define our required TypeConverter

public class TupleConverter<T1, T2> : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var elements = Convert.ToString(value).Trim('(').Trim(')').Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return (elements.First(), elements.Last());
}
}

And now, you can alter the above code as

TypeDescriptor.AddAttributes(typeof((string, string)), new TypeConverterAttribute(typeof(TupleConverter<string, string>)));
var json = JsonConvert.SerializeObject(dictionary);
var result = JsonConvert.DeserializeObject<Dictionary<(string, string), string>>(json);

With the magic portion of TypeConverter in place, your code would now work fine. Happy Coding.

Json Recipies – Part 2

Continuing with our earlier post on Json Recipies, let’s explore couple of quick reference recipes using the famous NewtonSoft.Json.

Recipe 04: Deserialize to Anonymous Type

One of the least explored feature in NewtonSoft is the ability to deserialize a Json to anonymous type. For example,

var json = @"{'Name':'anu viswan','Location':'india'}";
var anonymousType = new {Name = string.Empty, Location = string.Empty};

var result = JsonConvert.DeserializeAnonymousType(json, anonymousType);
Console.WriteLine($"Name : {result.Name}, Location:{result.Location}");

This would produce an output as

Name : anu viswan, Location:india

Isn’t that quite useful. You can now deserialize json directly to anonymous types, avoiding the need to declare a type for the purpose or going through tedious task of exploring the JObject. I believe this functionality is quite underused.

Recipe 05: Formatting Json as camelCase.

What if you come across a situation wherein, you want to format the Json with keys in camelCase. For example, consider the following json.

{'FirstName':'Anu','LastName':'Viswan','Age':35}

You would like to format the json such that the keys are rewritten as firstName,lastName and age. This is where CamelCasePropertyNamesContractResolver comes into picture. You could set the ContractResolver to CamelCasePropertyNamesContractResolver using the following.

var json = @"{'FirstName':'Anu','LastName':'Viswan','Age':35}";
var student = JsonConvert.DeserializeObject(json);
var camelSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
var result = JsonConvert.SerializeObject(student,camelSettings);

Where Student is defined as

public class Student
{
public string FirstName{get;set;}
public string LastName{get;set;}
public int Age{get;set;}
}

This would format the json string with all keys in camelCase.

So far, we have examined a simple json. Let’s expand the example for a complex nested version that happens to have a property of Type object, which encapsulate the nested json part. For example, what if the json in question is as follows

{"FirstName":"Anu","LastName":"Viswan","age":35,"SkillSet":{"ProgrammingLanguages":"C#,Dart","Database":"Sql Server,MySql,MongoDb"}}

This is where things get interesting. If you were to define a Property of Type Object in the Student Class, you could be suprised that the inner object wasn’t camelCased. Let’s check by adding a Property called SkillSet of Type object in Student.

public class Student
{
public string FirstName{get;set;}
public string LastName{get;set;}
public int Age{get;set;}
public object SkillSet{get;set;}
}

If we were to run the client code using CamelCasePropertyNamesContractResolver as described above, the output would be as following.

{"firstName":"Anu","lastName":"Viswan","age":35,"skillSet":{"ProgrammingLanguages":"C#,Dart","Database":"Sql Server,MySql,MongoDb"}}

As you can observe, the inner Object didn’t have its keys formatted with CamelCase.

The trick lies in most unexpected corner. Infact, you do not even need the Student Class. All you need is the ExpandoObject. Let’s rewrite the client code using ExpandoObject.

var json = @"{'FirstName':'Anu','LastName':'Viswan','Age':35, SkillSet:{ProgrammingLanguages:'C#,Dart',Database:'Sql Server,MySql,MongoDb'}}";
var student = JsonConvert.DeserializeObject(json);

var camelSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
var result = JsonConvert.SerializeObject(student,camelSettings);

That’s all the magic you needed. Now the formatting for inner Object is magically fixed.

{"firstName":"Anu","lastName":"Viswan","age":35,"skillSet":{"programmingLanguages":"C#,Dart","database":"Sql Server,MySql,MongoDb"}}

Recipe 06: Search and Replace using JObject.

There might be situations which forces you to use JObject for parsing json. Yes, it is inconvenient way of doing it, but sometimes you need to walk the hard path ( or should I say, sometimes JObject is the most convenient option).

How could you search and replace a token in JObject, especially if you do not know the names of parent node. For example, let us consider the following two json strings.

{'Fields' : { 'CA' : 'P' , 'MA' : { 'COLL': 'Q'} } }
{'Item' : { 'PA' : 'P' , 'VA' : { 'COLL': 'D'} } }

You are supposed to update the Value of COLL. However, as you can observe from the two Jsons available, the parents nodes are different.

Updating COLL would have been tough task. But there are few interesting methods in JObject makes our life easier.

To Select the COL token in either of the Json, you could use the SelectToken method

jobject.SelectToken("$..COLL");

For updating the value, you could use the Replace method. For example,

jobject.SelectToken("$..COLL").Replace(1);

That would give use the output we require. The output of above given samples would be as follows.

// Example 1
{
"Fields": {
"CA": "P",
"MA": {
"COLL": 1
}
}
}

// Example 2
{
"Item": {
"PA": "P",
"VA": {
"COLL": 1
}
}
}

Json Custom Filtering : Remove Properties of a Type T

One of the recent questions that came up in SO which fascinated me was how do one filter a Json string by removing properties from Json, which is of a particular Type. For example, consider the following Json.

{
'widget':
{
'debug': 'on',
'window': {
'title': 'Sample Widget',
'name': 'main_window',
'width': 500,
'height': 500
},
'image': {
'src': 'Images/Sun.png',
'name': 'sun1',
'hOffset': 250,
'vOffset': 250,
'alignment': 'center'
},
'text': {
'data': 'Click Here',
'size': 36,
'style': 'bold',
'name': 'text1',
'hOffset': 250,
'vOffset': 100,
'alignment': 'center',

}
}}

What if you want to remove all Json Properties that has a value of Integer Type. What would be a good way to achieve it if the format of Json is unknown ?

I ended up writing an extension method.

public static class Extensions
{
public static JToken RemoveFieldTypes(this JToken token,params JTokenType []fieldTypes)
{
JContainer container = token as JContainer;
if (container == null) return token;

var tokensToRemove = new List<JToken>();
foreach (JToken el in container.Children())
{
JProperty p = el as JProperty;
if(p!=null && fieldTypes.Contains(p.Value.Type))
{
tokensToRemove.Add(el);
}
el.RemoveFieldTypes(fieldTypes);
}
foreach (JToken el in tokensToRemove)
{
el.Remove();
}
return token;
}
}

Client Code Sample

JToken nodeList = JToken.Parse(strJson);
nodeList.RemoveFieldTypes(JTokenType.Integer);

Sample Ouput

{
"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window"
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"alignment": "center"
},
"text": {
"data": "Click Here",
"style": "bold",
"name": "text1",
"alignment": "center"
}
}
}

Json : Fetch all keys using Linq

Given a Json, how do we get all the keys in it ? Just the keys. For example, Consider the Json below.

{
Person:['Jia Anu', 'Anu Viswan','Sreena Anu'],
Details:[
{
Name: 'Jia Anu',
Age:3,
},
{
Name: 'Anu Viswan',
Age:35,
},
{
Name: 'Sreena Anu',
Age:34,
}
],
Address : 'Address here',
State : 'Kerala',
Country : 'India'
}

Given the above Json, you would like to get all the keys. You might be later interested to show this as a Menu or Dropdown, that’s down to the requirements. But, how do we get the keys in first place ? May be a Linq One liner would be great ?

Person
Details
Details.Name
Details.Age
Address
State
Country

Of course, you do have the option to loop through the JTokens, but the easiest way out would be using Linq.

var data = JObject.Parse(jsonString);
var result = data.Descendants()
.OfType<JProperty>()
.Select(f=>Regex.Replace(f.Path,@"\[[0-9]\]",string.Empty))
.Distinct();

The Regex involed is to ensure the arrays indices are removed and keys in arrays aren’t duplicated. The output of above Linq would give you collection of all keys in the Json as expected.

Json Recipes

Here are few quick recipes with Newtonsoft.Json

Recipe 01 : Convert Json to XML

One way to convert a Json to XML would be to convert Json to intermediate class structure and then serialize the class using XMLSerializer. But why go the long way when you can do it directly.

Let’s check the code straightaway.

var jsonString = @"{
'Family':[
{
'Name':'Anu',
'Age': '35'
},
{
'Name':'Jia',
'Age': '2'
}
]
}";
var xml = (XmlDocument)JsonConvert.DeserializeXmlNode(jsonString,"root");

That’s it, you have your XML. Output is shown below.

<root>
<Family>
<Name>Anu</Name>
<Age>35</Age>
</Family>
<Family>
<Name>Jia</Name>
<Age>2</Age>
</Family>
</root>

Recipe 02 : Convert XML to Json

No prizes for guess how to do it other way around (XML to Json) – Yes, you Serialize.

var xmlString = @"<root>
<Family>
<Name>Anu</Name>
<Age>35</Age>
</Family>
<Family>
<Name>Jia</Name>
<Age>2</Age>
</Family>
</root>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
var json = JsonConvert.SerializeXmlNode(doc);

Recipe 03: Dynamic Json
Consider the following Json. What could be the best way to model it in C# class.

{
'Key1' : 'some value 1',
'Key2' : 'some value 1',
'Key3' : 'some value 1',
'Key4' : 'some value 1',
}

Where you do not know how many Keys would be there and what could be there name ? The easiest way would be if you can serialize it to an Dictionary. The ‘JsonExtensionData‘ attribute allows you to do exactly the same.

<br />public class JsonSample
{
[JsonExtensionData]
public Dictionary<string,object> RandomKeyValuePair {get;set;}
}

// Client Code
var jsonString = @"
{
'Key1' : 'some value 1',
'Key2' : 'some value 1',
'Key3' : 'some value 1',
'Key4' : 'some value 1',
}";

var jsonSampleObject = JsonConvert.DeserializeObject<JsonSample>(jsonString);

Of course the reverse is also possible.

var jsonResult = JsonConvert.SerializeObject(jsonSampleObject);

More recipes later.