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?
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;
}
}
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;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.