自定义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
相关产品推荐
相关产品推荐

