非常简单的例子(我在单元测试中使用它):
private interface ISampleSubset
{
int id { get; }
}
private class Sample : ISampleSubset
{
public int id { get; set; }
public string name { get; set; }
}
下面是一个关于NewtonSoft JSON Serialize的小包装:
public string Serialize<T>(T t)
{
using (var sw = new StringWriter())
{
using (var jw = new JsonTextWriter(sw))
{
var js = JsonSerializer.Create();
js.Serialize(jw, t);
jw.Flush();
}
return sw.GetStringBuilder().ToString();
}
}
现在我想序列化ISampleSubset:然后这样命名:
ISampleSubSet t = new Sample()
{
id = 1,
name = "joe"
};
string json = Serialize(t);
我期望得到
{"id":1}
但我得到的却是
{"id":1,"name":"joe"}
我猜是js。Serialize使用反射来"查看"接口外部对象的其他属性。如何将其限制在界面上的那些属性?
序列化器甚至不知道你的接口,所以它给你所有的东西——它接受一个object
,所以它不知道你已经声明了ISampleSubset
类型的变量——它只知道对象本身是Sample
的一个实例。
可能不是最好的解决方案,但是您可以使用JsonConverter
来限制出现在序列化对象中的属性。
这段代码可能非常低效——请不要评判——只是把它放在一起,你可以清理细节并实现你需要的任何东西:
public class MyConverter<T> : JsonConverter {
private readonly string[] _propertyNames;
public MyConverter() {
_propertyNames = typeof(T).GetProperties().Select(p => p.Name).ToArray();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
var objectType = value.GetType();
var newObject = new Dictionary<string, object>();
foreach (string propName in _propertyNames) {
var prop = objectType.GetProperty(propName);
if (prop != null) {
newObject[propName] = prop.GetValue(value, null);
}
}
string s = JsonConvert.SerializeObject(newObject);
writer.WriteRaw(s);
}
public override bool CanConvert(Type objectType) {
return true; // ?
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
throw new NotImplementedException();
}
}
public static string Serialize<T>(T t) {
return JsonConvert.SerializeObject(t, new MyConverter<T>());
}
基本上它所做的是使用接口类型上的反射来检索其属性,然后仅使用在接口上找到的属性创建字典(您可以通过多种方式做到这一点)-然后使用简单的JsonConvert
类来序列化字典。
NewtonSoft。JSON根据默认规则(在。net 3.5 IIRC中)序列化你创建的对象实例,默认情况下,对象的所有属性都是可序列化的。如果你将变量声明为接口类型并不重要,因为它可能通过反射来进行序列化。
如果你想限制被序列化的属性,最好的方法是使用nonserialized属性