我知道Json.NET支持使用ShouldSerialize{PropName}
但有没有办法阻止整个类型被序列化而不改变引用它的类型? e.g。
public class Foo
{
public bool Enabled {get;set;}
...other properties
}
public class Bar
{
public Foo SomeFoo {get;set;}
public Foo OtherFoo {get;set;}
}
我希望Bar
类型不包括SomeFooo或OtherFoo,具体取决于是否设置了Enabled属性。如果SomeFoo.Enabled = false,则不应序列化Bar.SomeFoo。
所以我想要一个引用属性的条件序列化。 我不希望消费Foo类型有任何额外的代码或属性。它应该全部采用Foo类型。
我可以在Bar中添加一个ShouldSerializeSomeFoo ..但这不是我想要的..
答案 0 :(得分:2)
您可以编写自定义JsonConverter
来处理Foo
的序列化。
我在下面写了一个非常基本的版本,但我建议你更深入地研究它。
此版本保留属性引用,只是不序列化对象。您还可以为Bar
编写转换器,忽略整个属性。
public class FooJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var foo = value as Foo;
if (foo == null || !foo.Enabled)
return;
writer.WriteStartObject();
writer.WritePropertyName("Enabled");
serializer.Serialize(writer, foo.Enabled);
//Write the rest of the serialization
writer.WriteEndObject();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize(reader, objectType);
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof (Foo);
}
}
用法:
var trueFoo = new Foo()
{
Enabled = true
};
var falseFoo = new Foo()
{
Enabled = false
};
var bar = new Bar()
{
SomeFoo = trueFoo,
OtherFoo = falseFoo
};
//{"SomeFoo":{"Enabled":true},"OtherFoo":null}
var json = JsonConvert.SerializeObject(bar, new FooJsonConverter());
答案 1 :(得分:2)
我认为此问题的最佳解决方案是编写自定义IContractResolver
。解析器可以以编程方式将ShouldSerialize
方法应用于包含Foo
的每个对象,该对象将依次检查Foo
实例以查看它是否已启用。如果不是,则该属性根本不会被序列化。
创建解析器的最简单方法是从DefaultContractResolver
派生它,然后覆盖CreateProperties
方法。以下是您需要的代码:
using System;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
class CustomResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
foreach (JsonProperty prop in properties)
{
if (prop.PropertyType == typeof(Foo))
{
prop.ShouldSerialize = obj =>
{
Foo foo = (Foo)type.GetProperty(prop.PropertyName).GetValue(obj);
return foo != null && foo.Enabled;
};
}
}
return properties;
}
}
您可以通过JsonSerializerSettings
应用自定义解析器,如下所示:
JsonSerializerSettings settings = new JsonSerializerSettings
{
ContractResolver = new CustomResolver(),
};
string json = JsonConvert.SerializeObject(objToSerialize, settings);
这是一个完整演示的小提琴:https://dotnetfiddle.net/wnLbyD