【问题标题】:Json.NET Serialization with Extra Properties; Preserving Serializer Settings具有额外属性的 Json.NET 序列化;保留序列化程序设置
【发布时间】:2014-12-02 17:31:26
【问题描述】:

我想在 JSON.NET 序列化类型时为特定类型的实例的 json 输出引入一些元数据属性。

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


我知道我可以实现 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) 最终会重新输入我的自定义 WriteJsonJsonConverter

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

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


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

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    我发现我可以实现自定义 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;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-01-25
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      • 2012-04-01
      • 1970-01-01
      • 2016-08-27
      • 2020-06-08
      相关资源
      最近更新 更多