I am not sure why anybody has not asked about this question yet but I am trying to serialize only simple types of a given object using IContractResolver
interface. I don't really want to mark each property using ShouldSerialize
method or JsonDataAttribute
or anything like this.
What I have done so far shown as following on LinqPad
Some sample classes to serialize
class Customer
{
public List<Order> Orders {get;set;}
public int CustomerId {get;set;}
public string[] Addresses {get;set;}
}
class Order
{
public int OrderId{get;set;}
public string Name {get;set;}
public int Amount {get;set;}
public Order PreviousOrder {get;set;}
}
An extension method to serialize all the objects
static class ExtensionMethods
{
public static string JsonSerialize (this object obj)
{
var settings = new JsonSerializerSettings();
settings.ContractResolver = new MyContractResolver();
settings.DefaultValueHandling = DefaultValueHandling.Ignore;
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
return JsonConvert.SerializeObject(obj,settings);
}
}
My Custom Contract Resolver Class
public class MyContractResolver: DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member,memberSerialization);
property.ShouldSerialize = instance => instance.GetType().IsPrimitive || instance.GetType() == typeof(string) || instance.GetType() == typeof(decimal);
return property;
}
}
and Main method:
void Main()
{
var customer = new Customer
{
Orders = ProduceSomeOrders(),
Addresses = new string[] {"9450 S. Small Street Dr.","9521 Flintstone Dr. S"},
CustomerId = 1
};
var jsonOrder = customer.JsonSerialize();
jsonOrder.Dump();
}
I only want to serialize sample types such as int
,double
,string
,decimal
,bool
etc. but not arrays, collections, custom objects etc. and it will only navigate the first level, not 2nd or more levels down. I really wonder why there is not any simple method which does this in Json.Net.
This is the output when I run this code: (an empty json)
{ }
I've realized one thing when I run this code, the first member
parameter passed into the CreateProperty
method is the main object itself which in this case is Customer
instance. But since this will work for all sort of types I just don't want to say instance.GetType() == typeof(Customer)
or something like this in the method. The expected output in this case is only CustomerId
in this case.
Do you know any graceful way to handle my problem?
JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object). If you serialize this result it will generate a text with the structure and the record returned.
Json.NET has excellent support for serializing and deserializing collections of objects. To serialize a collection - a generic list, array, dictionary, or your own custom collection - simply call the serializer with the object you want to get JSON for.
Json namespace provides functionality for serializing to and deserializing from JavaScript Object Notation (JSON). Serialization is the process of converting the state of an object, that is, the values of its properties, into a form that can be stored or transmitted.
DeserializeObject<T>(String,JsonConverter[]) Deserializes the JSON to the specified . NET type using a collection of JsonConverter. DeserializeObject(String, JsonSerializerSettings)
Instead of overriding CreateProperty
method, I am overriding GetSerializableObjects
method as it gives all the possible members I will get:
public class MyContractResolver: DefaultContractResolver
{
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var members = base.GetSerializableMembers(objectType);
var filteredMembers = new List<MemberInfo>();
members.ForEach(m=>{
if(m.MemberType == MemberTypes.Property)
{
PropertyInfo info = (PropertyInfo) m;
var type = info.PropertyType;
if(type.IsPrimitive || type == typeof(string) || type == typeof(decimal))
{
filteredMembers.Add(m);
}
}
});
return filteredMembers;
}
}
By changing the method below I got the result: {"CustomerId":1}. Is this what you were looking for?
public class MyContractResolver:DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member,memberSerialization);
var propertyType = property.PropertyType;
if(propertyType == typeof(int)
|| propertyType == typeof(string)){
property.ShouldSerialize = instance => true;
}
else
{
property.ShouldSerialize = instance => false;
}
return property;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With