Json.NET 整个类型的条件序列化



我知道 Json.NET 支持使用ShouldSerialize{PropName}的条件序列化

但是有没有办法防止在不更改引用它的类型的情况下序列化整个类型?例如

 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..但这不是我想要的。

您可以编写一个自定义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());

我认为这个问题的最佳解决方案是编写自定义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

相关内容

  • 没有找到相关文章

最新更新