14

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?

3
  • What is the expected outcome of the serialization? Based on what I read it should contain only CustomerID, is that correct? Commented Apr 10, 2013 at 15:36
  • @Patrick : You're right! Commented Apr 10, 2013 at 15:37
  • In the JsonSerialize method, is it possible to iterate the properties of the "top instance", in order to serialize its child properties, and then somehow mash them together into a valid json string? Commented Apr 10, 2013 at 15:39

2 Answers 2

6

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;
}
}
Sign up to request clarification or add additional context in comments.

Comments

4

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;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.