我不知道为什么有人还没有问过这个问题但是我试图使用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;
}
}
和主要方法:
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)
{}
我在运行此代码时意识到一件事,传递到member
方法的第一个CreateProperty
参数是主要对象本身,在本例中是Customer
个实例。但由于这适用于各种类型,我不想在方法中说instance.GetType() == typeof(Customer)
或类似的东西。在这种情况下,此情况下的预期输出仅为CustomerId
。
你知道有任何优雅的方式来处理我的问题吗?
答案 0 :(得分:5)
通过更改下面的方法,我得到了结果:{“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;
}
}
答案 1 :(得分:3)
我没有覆盖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;
}
}