MaxJsonLength error when using Json.Decode

Deserializing a JSON string natively in C# to a dynamic object can be achieved quite easily with the following line:

dynamic result = System.Web.Helpers.Json.Decode(someJsonString);

Generally this works fine until you pass in a particularly large chunk of data in which case you may get an exception

Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property. Parameter name: input

Some workarounds suggest adding to the web.config to override this value

<system.web.extensions>
    <scripting>
        <scriptResourceHandler enableCompression="true" enableCaching="true" />
            <webServices>
                <jsonSerialization maxJsonLength="2147483647" />
            </webServices>
     </scripting>
</system.web.extensions>

But this does not seem to work and internally it reverts back to a default setting. Nor does the next line

<appSettings>
    <add key="aspnet:MaxJsonLength" value="2147483647" />
</appSettings>

A few posts online suggest using JSON.Net which works well but results in a slightly different behaviour because it will not deserialize as dynamic. This means more checks are required in code to avoid exceptions when trying to access non existent elements or arrays.

For example with the true dynamic return type a check to see if a property exists is just a null check, but with JSON.Net this will likely result in an null ref exception.

Further suggestions involve using the System.Web.Extensions library and creating a System.Web.Script.Serialization.JavaScriptSerializer, which allows access to the MaxJsonLength property:

var serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue;

var result = serializer.DeserializeObject(data);

The issue here is that this will return a graph of string object dictionary and object arrays, which means we need to do lots of key exists and null reference checks in code.

A few other posts suggested recursively converting the Dictionary to a expando object allowing dynamic access, but this seemed like a potential performance issue. But looking at the actual source code for System.Web.Helpers.Json.Decode it turns out it is actually doing something similar behind the scenes.

It creates an instance of JavaScriptSerializer then wraps the deserialized object to allow dynamic access. It is a bit annoying that there is no way to specify the MaxJsonLength but as a work around the code can be reused as needed. A simplified example might be something along the lines of:

public static dynamic DecodeBigJson(string data)
{
    var serializer = new JavaScriptSerializer();
    serializer.MaxJsonLength = Int32.MaxValue;

    var value = serializer.DeserializeObject(data);

    var dictionaryValues = value as IDictionary<string, object>;
    if (dictionaryValues != null)
    {
        return new DynamicJsonObject(dictionaryValues);
    }

    var arrayValues = value as object[];
    if (arrayValues != null)
    {
        return new DynamicJsonArray(arrayValues);
    }

    return value;
}