简体   繁体   English

使用Json.Net仅序列化简单类型

[英]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. 我不知道为什么有人还没有问过这个问题,但我试图使用IContractResolver接口仅序列化给定对象的简单类型。 I don't really want to mark each property using ShouldSerialize method or JsonDataAttribute or anything like this. 我真的不想使用ShouldSerialize方法或JsonDataAttribute或类似的东西来标记每个属性。

What I have done so far shown as following on LinqPad 到目前为止我所做的事情在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. 我只想序列化样本类型,如intdoublestringdecimalbool等,但不是数组,集合,自定义对象等。它只会导航到第一级,而不是第二级或更多级。 I really wonder why there is not any simple method which does this in Json.Net. 我真的很想知道为什么在Json.Net中没有任何简单的方法可以做到这一点。

This is the output when I run this code: (an empty json) 这是我运行此代码时的输出:(一个空的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. 我在运行此代码时已经意识到一件事,传递给CreateProperty方法的第一个member参数是主对象本身,在本例中是Customer实例。 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. 但是因为这适用于所有类型的我只是不想说instance.GetType() == typeof(Customer)或类似的方法。 The expected output in this case is only CustomerId in this case. 在这种情况下,此情况下的预期输出仅为CustomerId

Do you know any graceful way to handle my problem? 你知道任何优雅的方式来处理我的问题吗?

By changing the method below I got the result: {"CustomerId":1}. 通过更改下面的方法,我得到了结果:{“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: 我没有覆盖CreateProperty方法,而是覆盖了GetSerializableObjects方法,因为它提供了我将获得的所有可能的成员:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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