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

Chi*_*iya 6 c# json json.net .net-core

我正在尝试解析 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.
Run Code Online (Sandbox Code Playgroud)

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

//**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);
Run Code Online (Sandbox Code Playgroud)

dbc*_*dbc 12

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

更改 - JsonReader 和 JsonSerializer MaxDepth 默认为 64

但是,他们没有添加MaxDepthto 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);
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 添加限制MaxDepth似乎是为了避免某种拒绝服务警告,请参阅ALEPH-2018004 - DOS 漏洞 #2457了解详细信息。

  • 似乎没有充分的理由解析为JObject然后反序列化为objectJObject默认情况下,Json.NET 会在反序列化到时将 JSON 对象反序列化为 a object(除非被 覆盖TypeNameHandling),所以你可以这样做

    var jObject = JsonConvert.DeserializeObject<object>(jsonString, settings);
    
    Run Code Online (Sandbox Code Playgroud)

    从而避免不必要的步骤。

  • 如果您正在使用,出于安全原因,TypeNameHandling您可能需要提供自定义。ISerializationBinder请参阅Newtonsoft Json 中的 TypeNameHandling 警告了解原因。

  • _似乎没有充分的理由解析为 JObject 然后反序列化为对象_ ...除非您需要将 JObject 转换为通用返回类型 `T` (2认同)