Chirag Bavaliya
Chirag Bavaliya

Reputation: 83

Newtonsoft: Getting "The reader's MaxDepth of 64 has been exceeded" error while parse json string into object

I am trying to parse json string to create DialogState object. However at some level I am getting following error while parsing a JSON string into an object:

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.

I am using following method to serialize and deserialize my object:

//**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);

Upvotes: 8

Views: 8894

Answers (1)

dbc
dbc

Reputation: 116585

In Json.NET 13.0.1, Newtonsoft changed the default MaxDepth for JsonReader (and hence all derived reader types including JsonTextReader) to 64:

Change - JsonReader and JsonSerializer MaxDepth defaults to 64

However, they did not add a MaxDepth to JsonLoadSettings, so JObject.Parse() (as well as JArray.Parse() and JToken.Parse()) will now throw if the input JSON depth exceeds 64 levels.

The easiest way to avoid this is to use JsonConvert.DeserializeObject<JObject>(string, JsonSerializerSettings) instead and set JsonSerializerSettings.MaxDepth to something large, as you are currently doing when serializing:

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);

Notes:

  • The MaxDepth limitation seems to have been added to avoid some sort of denial-of-service warning, see ALEPH-2018004 - DOS vulnerability #2457 for details.

  • There doesn't seem to be good reason to parse to a JObject then deserialize to object. By default Json.NET will deserialize a JSON object to a JObject anyway when deserializing to object (unless overridden by TypeNameHandling), so you could just do

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

    Thereby avoiding the unnecessary step.

  • If you are using TypeNameHandling you may want to provide a custom ISerializationBinder for security reasons. See TypeNameHandling caution in Newtonsoft Json for why.

Upvotes: 13

Related Questions