繁体   English   中英

自定义JsonConverter不应以TokenType“ EndObject”获取阅读器

[英]Custom JsonConverter gets reader with TokenType “EndObject” when it shouldn't be

我有一个带有JSON对象数组的流,这些对象以两种不同的格式出现,但包含相同类型的数据,并且我想将这两种格式反序列化为相同的类型,因此我的视图不需要为两种格式的自定义逻辑数据。 目前,我正在使用自定义JsonConverter处理此问题。

这是我的模型:

[JsonObject]
[JsonConverter(typeof(MyCommonObjectJsonConverter))]
public class MyCommonObject {
    // some common fields, e.g.
    public String Id { get; set; }
    public string Text { get; set; }
}

这是我自定义的JsonConverter:

public class MyCommonObjectJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // don't need to worry about serialization in this case, only
        // reading data
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jObject = JObject.Load(reader);

        MyCustomObject result;
        if (IsFormatOne(jObject))
        {
            // the structure of the object matches the first format,
            // so just deserialize it directly using the serializer
            result = serializer.Deserialize<MyCustomObject>(reader);
        }
        else if (IsFormatTwo(jObject))
        {
            result = new MyCustomObject();

            // initialize values from the JObject
            // ... 
        }
        else
        {
            throw new InvalidOperationException("Unknown format, cannot deserialize");
        }

        return result;
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(MyCustomObject).IsAssignableFrom(objectType);
    }

    // Definitions of IsFormatOne and IsFormatTwo
    // ...
}

但是,当我反序列化第一种格式的对象时,由于JsonReader的TokenType为“ EndToken”,我收到一条错误消息,指出它无法加载JObject。 我不确定为什么会这样,正在加载的数据格式正确。 关于我应该寻找的任何建议?

但是,当您读取MyCommonObject ,您想回到默认的反序列化:

  • 正如您所观察到的那样,对JObject.Load(reader)的调用已经使阅读器超越了该对象,并且
  • 在任何情况下,调用serializer.Deserialize<MyCustomObject>(reader)都会导致无限递归。

在这种情况下,避免在ReadJson()中进行不必要的递归的惯用方法是手动分配结果,然后调用serializer.Populate(jObject.CreateReader(), result) 即:

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;

        JObject jObject = JObject.Load(reader);

        MyCommonObject result;
        if (IsFormatOne(jObject))
        {
            result = (existingValue as MyCommonObject ?? (MyCommonObject)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator()); // Reuse existingValue if present
            // the structure of the object matches the first format,
            // so just deserialize it directly using the serializer
            using (var subReader = jObject.CreateReader())
                serializer.Populate(subReader, result);
        }
        else if (IsFormatTwo(jObject))
        {
            result = (existingValue as MyCommonObject ?? (MyCommonObject)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator());

            // initialize values from the JObject
            // ... 
        }
        else
        {
            throw new InvalidOperationException("Unknown format, cannot deserialize");
        }

        return result;
    }

在编写此代码时想出了原因,调用serializer.Deserialize<MyCustomObject>(reader)再次递归到我的转换器中,此时,读取器将从加载到JObject中到达结束令牌,从而使TokenType等于EndToken。 我应该更仔细地检查堆栈跟踪。 现在,我将为两种格式编写自定义初始化逻辑,以使模型类与格式无关。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM