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

本文关键字:简单 类型 序列化 Json Net 使用 | 更新日期: 2023-09-27 18:08:33

我不知道为什么还没有人问过这个问题,但我正试图使用IContractResolver接口序列化给定对象的简单类型。我真的不想用ShouldSerialize方法或JsonDataAttribute或类似的方法标记每个属性。

到目前为止,我在LinqPad 上所做的如下所示

要序列化的一些样例类

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

序列化所有对象的扩展方法

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

我的自定义契约解析器类

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

和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();
}

我只想序列化示例类型,如int, double, string, decimal, bool等,但不是数组,集合,自定义对象等,它只会导航第一级,而不是第二级或更低的级别。我真想知道为什么在Json.Net中没有任何简单的方法来做到这一点。

这是我运行这段代码时的输出:(一个空json)

{}

当我运行这段代码时,我意识到一件事,传递到CreateProperty方法的第一个member参数是主对象本身,在这种情况下是Customer实例。但由于这将适用于所有类型,我只是不想在方法中说instance.GetType() == typeof(Customer)或类似的东西。本例中期望的输出仅为CustomerId

你知道什么优雅的方法来处理我的问题吗?

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

通过更改下面的方法,我得到了结果:{"CustomerId":1}。这就是你要找的吗?

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

我不是重写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;
    }
}