You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Newtonsoft.Json转换器反序列化遇JsonReaderException问题排查

自定义Newtonsoft.Json转换器反序列化问题排查

问题描述

我尝试序列化一个UI树,因仅需对象的少量数据,编写了自定义Newtonsoft.Json转换器。序列化逻辑可正常生成指定格式的JSON,但反序列化时,在LoadFromJson方法中访问reader.Value返回null,调用ReadAsString()则抛出异常:

Newtonsoft.Json.JsonReaderException: Unexpected state: ObjectStart. Path 'NavTree', line 669, position 14。

相关代码

自定义转换器代码

public override void WriteJson(JsonWriter writer, NavTree value, JsonSerializer serializer)
{
    value.SaveAsJson(writer);
}

public override NavTree ReadJson(JsonReader reader, Type objectType, NavTree existingValue, bool hasExistingValue,
    JsonSerializer serializer)
{
    NavTree tree = hasExistingValue ? existingValue : new NavTree();
    tree.LoadFromJson(reader);
    return tree;
}

序列化方法

public void SaveAsJson(JsonWriter writer)
{
    SerializableTreeItem root = new (this.GetRoot());
    JObject.FromObject(root).WriteTo(writer);
}

生成的JSON示例

"NavTree": {
    "Id": "All",
    "IsCategory": true,
    "Children": [
      {
        "Id": "https://popularresistance.org/feed/",
        "IsCategory": false,
        "Children": []
      },
      {
        "Id": "https://www.aljazeera.com/xml/rss/all.xml",
        "IsCategory": false,
        "Children": []
      }
    ]
}

反序列化方法

public void LoadFromJson(JsonReader reader)
{
    SerializableTreeItem loaded =
        JsonConvert.DeserializeObject<SerializableTreeItem>((string)reader.Value ?? string.Empty);
    if (loaded == null) return;
    if (this.GetRoot() != null)
    {
        this.GetRoot().Free();
        TreeItem root = this.CreateItem();
        root.SetMetadata(0, RootMetaDataId);
    }

    this.AddItem(loaded, this.GetRoot());
}

排查方向

  • 理解JsonReader的状态逻辑:当前reader处于ObjectStart状态(对应JSON对象的{),此时reader.Value必然为null,ReadAsString()也仅能在reader指向字符串值时调用,直接操作会触发状态异常。
  • 利用JsonSerializer直接反序列化:不要尝试把reader.Value转成字符串再反序列化,而是将JsonSerializer实例传入LoadFromJson,直接用它读取当前reader指向的对象节点:
    修改LoadFromJson方法:
    public void LoadFromJson(JsonReader reader, JsonSerializer serializer)
    {
        SerializableTreeItem loaded = serializer.Deserialize<SerializableTreeItem>(reader);
        if (loaded == null) return;
        if (this.GetRoot() != null)
        {
            this.GetRoot().Free();
            TreeItem root = this.CreateItem();
            root.SetMetadata(0, RootMetaDataId);
        }
    
        this.AddItem(loaded, this.GetRoot());
    }
    
    同时更新ReadJson方法,传入serializer:
    public override NavTree ReadJson(JsonReader reader, Type objectType, NavTree existingValue, bool hasExistingValue,
        JsonSerializer serializer)
    {
        NavTree tree = hasExistingValue ? existingValue : new NavTree();
        tree.LoadFromJson(reader, serializer);
        return tree;
    }
    
  • 手动遍历节点(备选方案):如果需要自定义读取逻辑,可以手动控制reader的读取流程:调用reader.Read()进入对象,循环读取属性名和对应值,直到读到JsonToken.EndObject。这种方式适合精细控制,但代码量更大。
  • 检查JSON完整性:确认生成的JSON结构完整(比如示例中是否有闭合的}和]),不完整的JSON会导致读取状态异常。

内容的提问来源于stack exchange,提问作者user3190036

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 02:05:17