简体   繁体   中英

Serialize only simple types using Json.Net

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM