【问题标题】:Json.NET custom serialization with JsonConverter - how to get the "default" behavior使用 JsonConverter 进行 Json.NET 自定义序列化 - 如何获得“默认”行为
【发布时间】:2016-06-05 20:20:42
【问题描述】:

我的类 DataType 有一个 JsonConverter。 当在 Json 中使用纯字符串作为 DataType 类型属性的值时,我想做一些特殊处理。在值是“完整”对象的情况下,我想做“正常”反序列化。

这是我的尝试

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    if (reader.Value != null && reader.ValueType == typeof (string))
    {
        return someSpecialDataTypeInstance;
    }
    else if (reader.TokenType == JsonToken.StartObject)
    {
        DataType dataType = serializer.Deserialize<DataType>(reader);
        return dataType;
    }
    else
    {
        throw new JsonSerializationException();
    }
}

但这不起作用,因为这一行: DataType dataType = serializer.Deserialize(reader); 导致无限递归。

这能以某种方式轻松完成吗? (无需手动逐个属性)

【问题讨论】:

标签: c# json serialization json.net


【解决方案1】:

一种简单的方法是分配一个类的实例,然后使用JsonSerializer.Populate(JsonReader, Object)。这是标准CustomCreationConverter&lt;T&gt;中的做法:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    if (reader.Value != null && reader.ValueType == typeof(string))
    {
        return someSpecialDataTypeInstance;
    }
    else if (reader.TokenType == JsonToken.StartObject)
    {
        existingValue = existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
        serializer.Populate(reader, existingValue);
        return existingValue;
    }
    else if (reader.TokenType == JsonToken.Null)
    {
        return null;
    }
    else
    {
        throw new JsonSerializationException();
    }
}

限制:

示例fiddle

【讨论】:

  • DefaultConvert() 调用在 Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter 转换器,JsonReader 读取器,类型 objectType,Object existingValue)处引发 NRE。我用直接构造函数调用替换了它......除此之外,谢谢你的回答!
  • @j_maly - 我遇到了同样的问题,但我无法根据您的评论找出解决方案。您可以发布您对此答案所做的修改吗?
  • @dbc - 感谢您发布该小提琴。看来您仍在调用 DefaultCreator()。像 j_maly 一样,我在 DefaultCreator() 上收到 NullReferenceException。 j_maly 说“我用直接构造函数调用替换它”,但我无法解释他/她的意思。我正在寻找替换/修复来解决 NullReferenceException 问题。
  • @SFun28 - 你的类型有公共无参数构造函数吗?如果不是那可能是问题所在。如果您的类型只有一个构造函数,并且该构造函数是参数化的,那么DefaultCreator() 将不起作用。相反,您必须通过调用 new MyType(arg1, arg2, ... ) 手动构造您的类型。
  • @dbc - 我的类型没有公共无参数构造函数。我确实有一个定制的合同解析器。我也知道,如果我的 JsonConverter 为 CanConvert 返回 false,则 json.net 能够使用自定义的合约解析器反序列化类型。这会带来任何选择吗?
猜你喜欢
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
  • 2021-04-02
  • 1970-01-01
  • 2014-02-17
  • 2016-03-28
  • 2018-06-05
相关资源
最近更新 更多