Newtonsoft:将 json 字符串解析为对象时出现“已超出读者的 MaxDepth 64”错误

Posted

技术标签:

【中文标题】Newtonsoft:将 json 字符串解析为对象时出现“已超出读者的 MaxDepth 64”错误【英文标题】:Newtonsoft: Getting "The reader's MaxDepth of 64 has been exceeded" error while parse json string into object 【发布时间】:2021-10-05 03:53:42 【问题描述】:

我正在尝试解析 json 字符串以创建 DialogState 对象。但是在某种程度上,我在将 JSON 字符串解析为对象时遇到了以下错误:

The reader's MaxDepth of 64 has been exceeded. Path 'DialogState.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.dialogs.dialogStack.$values[0].state.options.Prompt.attachments.$values', line 1, position 7999.

我正在使用以下方法来序列化和反序列化我的对象:

//**For serialize**
var _jsonSerializer = JsonSerializer.Create(new JsonSerializerSettings  TypeNameHandling = TypeNameHandling.All, MaxDepth = 128 );

var json = JObject.FromObject(change.Value, _jsonSerializer);
var jsonString = json.ToString(Formatting.None);

//**For deserialize**
var jObject = JObject.Parse(jsonString).ToObject(typeof(object), _jsonSerializer);

【问题讨论】:

【参考方案1】:

在 Json.NET 13.0.1 中,Newtonsoft 将 JsonReader(以及包括 JsonTextReader 在内的所有派生阅读器类型)的默认 MaxDepth 更改为 64

更改 - JsonReader 和 JsonSerializer MaxDepth 默认为 64

但是,他们没有将 MaxDepth 添加到 JsonLoadSettings,因此如果输入 JSON 深度超过 64 级,JObject.Parse()(以及 JArray.Parse()JToken.Parse())现在将抛出。

避免这种情况的最简单方法是改用JsonConvert.DeserializeObject<JObject>(string, JsonSerializerSettings) 并将JsonSerializerSettings.MaxDepth 设置为较大的值,就像您当前在序列化时所做的那样:

var settings = new JsonSerializerSettings  TypeNameHandling = TypeNameHandling.All, MaxDepth = 128 ;
var _jsonSerializer = JsonSerializer.Create(settings);
var jObject = JsonConvert.DeserializeObject<JObject>(jsonString, settings).ToObject(typeof(object), _jsonSerializer);

注意事项:

似乎已添加MaxDepth 限制以避免某种拒绝服务警告,有关详细信息,请参阅ALEPH-2018004 - DOS vulnerability #2457。

似乎没有充分的理由先解析为JObject,然后反序列化为object。默认情况下,当反序列化为object(除非被TypeNameHandling 覆盖)时,无论如何,Json.NET 都会将 JSON 对象反序列化为JObject,所以你可以这样做

var jObject = JsonConvert.DeserializeObject<object>(jsonString, settings);

从而避免了不必要的步骤。

如果您使用TypeNameHandling,出于安全原因,您可能需要提供自定义ISerializationBinder。请参阅 TypeNameHandling caution in Newtonsoft Json 了解原因。

【讨论】:

以上是关于Newtonsoft:将 json 字符串解析为对象时出现“已超出读者的 MaxDepth 64”错误的主要内容,如果未能解决你的问题,请参考以下文章

关于Newtonsoft.Json解析json字符串

C# 使用 Newtonsoft 解析 JSON

如何使用 Newtonsoft.Json 将包含数组数组的 json 对象解析为 C# 中的对象列表?

Newtonsoft.Json使用

C# Newtonsoft.Json解析json字符串处理 - JToken 用法

C# Newtonsoft.Json解析json字符串处理(最清晰易懂的方法)