Json.NET 具有额外属性的序列化;保留序列化程序设置

本文关键字:序列化 保留 程序 设置 属性 NET Json | 更新日期: 2023-09-27 18:32:59

我想在序列化

特定类型实例的 json 输出中引入一些元数据属性 JSON.NET 该类型。

在保留序列化上下文和设置的同时引入这些附加属性的最佳方法是什么?


我知道我可以实现一个JsonConverter并将其添加到序列化程序设置中。 下面是WriteJson的示例实现:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    var Json = JObject.FromObject(value, serializer);
    //modify Json by adding some properties ...
    Json.WriteTo(writer);
}

但是,这带来了一些我不确定如何解决的问题:

如果通过设置配置序列化程序:

ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore

然后尝试调用 JObject.FromObject(value, serializer) 不会序列化任何内容,因为 JSON.NET 已经确定该值正在序列化(因此它会忽略序列化同一引用的进一步尝试(。

如果我设置ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize那么我最终会得到一个无限递归循环。 打电话给JObject.FromObject(value, serializer)最终会重新输入我的自定义JsonConverter WriteJson

相反,如果我创建新的序列化程序或调用JObject.FromObject(value)(如本例所示(,我将不再使用相同的序列化程序设置。 虽然输出将具有额外的属性,但如果已为原始序列化程序配置了其他转换器、协定解析器等,则它可能与序列化 json 的其余部分不匹配。 此外,我丢失了引用循环处理的序列化上下文,因此将不再跳过在原始输出中跳过的引用。

有没有更好的方法来挂钩到序列化过程,允许您修改原始序列化程序生成的 json?


更新:目前,我已经实施了一个不太理想的解决方法,即为我的自定义JsonConverter提供设置工厂Func<JsonSerializerSettings>。提供的设置必须排除转换器以避免递归循环,这不会保留序列化上下文。此外,任何嵌套对象都不会收到其他属性,因为转换器不再配置。

Json.NET 具有额外属性的序列化;保留序列化程序设置

我发现我可以实现自定义IContractResolver并覆盖CreateProperties以包含任意数量的附加属性以及提供实际属性值的IValueProvider

此方法不是编写 JsonConverter 来序列化对象,然后添加属性,而是修改序列化程序随后使用的特定类型的协定。

protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
    var Result = base.CreateProperties(type, memberSerialization);
    //check if this is a type we add properties to
    if (IsAnnotatedType(type))
    {
        Result.Add(new JsonProperty
        {
            PropertyType = typeof(string),
            PropertyName = "AdditionalProperty",
            Readable = true,
            Writable = false,
            //value provider will receive the object instance when GetValue is called
            ValueProvider = new AdditionalPropertyValueProvider()
        });
    }
    return Result;
}