using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using Newtonsoft.Json.Serialization;
using System.Linq;
using System.Reflection;
public interface IParent
{
[JsonProperty]
int Id {get;set;}
}
[JsonObject(MemberSerialization.OptIn)]
public class Parent : IParent
{
public int Id { get;set; }
public string Name {get;set;}
}
public class Serializer
{
public static void Main()
{
var parent = new Parent() { Id = 1, Name ="Parent"};
var sb = new StringBuilder();
var sw = new StringWriter(sb);
var settings = new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore
};
var output = JsonConvert.SerializeObject(parent, Formatting.None, settings);
Console.WriteLine(output);
Console.ReadKey();
}
}
在上面的代码中,输出是{}。是否可以将输出序列化为 {"Id":1}?
这是个坏主意。
话虽如此,Newtonsoft 为您提供了一种更改序列化内容的方法:在这种情况下,您可以子类化 DefaultContractResolver
。并覆盖 CreateProperty
。
问题是,根据接口(interface)的属性决定何时选择加入序列化并不容易。一方面,一个类可能会使用相互冲突的序列化指令实现多个接口(interface)。此外,反序列化一个对象到声明为冲突接口(interface)(例如)的变量中是行不通的。它很脆弱且不安全(它允许外部代码指定实例显示的数据)。
如果您必须这样做,下面的代码适用于您的情况:
public class InterfaceContractResolver : DefaultContractResolver, IContractResolver
{
public InterfaceContractResolver() : this(false) { }
public InterfaceContractResolver(bool shareCache) : base (shareCache) {}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
var interfaces = member.DeclaringType.GetInterfaces();
foreach (var @interface in interfaces)
{
foreach (var interfaceProperty in @interface.GetProperties())
{
// This is weak: among other things, an implementation
// may be deliberately hiding an interface member
if (interfaceProperty.Name == member.Name && interfaceProperty.MemberType == member.MemberType)
{
if (interfaceProperty.GetCustomAttributes(typeof(JsonPropertyAttribute), true).Any())
{
property.Ignored = false;
return property;
}
}
}
}
return property;
}
}
然后,当您创建序列化器时,在设置中将解析器实例传递给它:
var settings = new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new InterfaceContractResolver(true)
};