What exceptions does Newtonsoft.Json.DeserializeObject throw?
Asked Answered
A

5

165

What exceptions does Newtonsoft.Json.DeserializeObject throw? I want to handle them.

http://james.newtonking.com/json/help/?topic=html/M_Newtonsoft_Json_JsonConvert_DeserializeObject.htm#seeAlsoToggle

Affiliate answered 8/10, 2014 at 19:6 Comment(1)
Why everywhere exceptions are not well documented? Annoying :(Revelation
Q
180

JSON.NET defines the following exceptions:

  • JsonException
    • JsonReaderException
    • JsonSerializationException
    • JsonWriterException
    • JsonSchemaException

Serialization or deserialization errors will typically result in a JsonSerializationException.

Quilt answered 8/10, 2014 at 19:28 Comment(8)
Thanks, but "typically"? How can I find out for certain which exceptions DeseriazeObject throws?Affiliate
@cja, I think it will always be JsonSerializationException, but to be sure you would have to ask the author or look into the source code... Anyway, you can just catch JsonException if you want to be sure not to miss anything, since all JSON.NET exceptions inherit from it.Quilt
I think exceptions need to be properly documented.Raspings
I get the same exception detail, even with Exception class in the catch block, can you please help me understand how they work! In my case right now getting exception with JSON that has unicode, online tool able to parse it correctly but failing with JSONConvertSteck
@Raspings thats a nice think u got there broJaimeejaimes
The exception depends on what actually failed, for example, I took some valid JSON and removed the closing '}' and it threw a JsonSerializationException. Yet if I change it to be not JSON like at all (i.e. just a word or even HTML), it threw JsonReaderException.Trustbuster
Deserialization with JsonConvert.DeserializeObject just threw a JsonReaderException for me (not a JsonSerializationException).Iphigeniah
I note that if the type T being serialized within JsonConvert.DeserializeObject<T> has a [JsonConstructor] that throws ArgumentException for invalid ctor parameter arguments (as it should...) then DeserializeObject<T>(String) will not catch-and-wrap those ArgumentException objects - so that's something to consider...Nevski
S
84

Note that Json.NET's error handling documentation shows a strategy for the API user to deal with errors by handling error events rather than directly catching exceptions. This makes sense when you consider that perhaps only one item in an array may fail to deserialize, and you might want to handle this in a more granular fashion than one monolithic exception for the entire set.

This answer addresses the "want to handle them" part of your question without getting at the "what exceptions" part. As another answer shows, all Json.NET exceptions inherit from JsonException Class, so catching this would be a nice fail-safe. However, it seems that if you want to really understand what caused an exception to be thrown, you would need to read its Message property, not handle based on the Exception type, as the different types seem to be more oriented on the action you are performing than the error category. In the following example code, the args.ErrorContext.Error is an instance of Exception.

Example code from the documentation:

List<string> errors = new List<string>();

List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(@"[
      '2009-09-09T00:00:00Z',
      'I am not a date and will error!',
      [
        1
      ],
      '1977-02-20T00:00:00Z',
      null,
      '2000-12-01T00:00:00Z'
    ]",
    new JsonSerializerSettings
    {
        Error = delegate(object sender, ErrorEventArgs args)
        {
            errors.Add(args.ErrorContext.Error.Message);
            args.ErrorContext.Handled = true;
        },
        Converters = { new IsoDateTimeConverter() }
    });

// 2009-09-09T00:00:00Z
// 1977-02-20T00:00:00Z
// 2000-12-01T00:00:00Z

// The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.
// Unexpected token parsing date. Expected String, got StartArray.
// Cannot convert null value to System.DateTime.
Samanthasamanthia answered 8/1, 2016 at 17:59 Comment(0)
L
2

Its JsonReaderException.

Check below:

enter image description here

And it can be handled easily

enter image description here

Lyonnais answered 16/9, 2020 at 9:35 Comment(1)
I got a JsonSerializationException when I tried to deserialize an array as a JObject, so this doesn't catch everythingRademacher
N
0

(9 years later and no-one spotted this one yet? Yikes)

In addition to JSON.NET's own exception supertype (JsonException) that everyone else has mentioned already, today I noticed today that any exception thrown by the types-being-deserialized are not intercepted by JSON.NET.

...I was hoping that JsonConvert.DeserializeObject would catch any ArgumentException thrown from a deserialized-type's ctor (for example) and repackage at as an InnerException in a newly-thrown JsonException - because that would make sense and would be keeping with JSON.NET's reputation for having a novice-friendly API design; nope: instead any thrown exception will simply continue up the stack.

Consequently, my copypasta JSON deserialization code now looks like this:

TDataTransferObject obj;
try
{
    obj = JsonConvert.DeserializeObject<TDataTransferObject>( jsonText ) ?? throw new JsonException( "Input JSON was deserialized to null" );
}
catch( ArgumentException argEx )
{
    throw new JsonException( "Failed to deserialize JSON: " + argEx.Message, argEx );
}
#if HANDLE_JSON_EX
catch( JsonException jsonEx )
{
    // TODO: Handle gracefully.
}
#endif

To verify this, I ran this in Linqpad 7 with Newtonsoft.Json v13.0.3:

void Main()
{
    const String json = @"{ ""foo"": null, ""bar"": 4096 }";
    
    Dto dto;
    try
    {
        dto = JsonConvert.DeserializeObject<Dto>( json );
    }
    catch( Exception ex )
    {
        ex.Dump();
    }
}

class Dto
{
    [JsonConstructor]
    public Dto(
        [JsonProperty( "foo" )] String foo,
        [JsonProperty( "bar" )] Int32  bar
    )
    {
        this.Foo = foo             ?? throw new ArgumentNullException(nameof(foo));
        this.Bar = bar < 1024 ? bar : throw new ArgumentOutOfRangeException( paramName: nameof(bar), actualValue: bar, message: "Value must be under 1024." );
    }
    
    [JsonProperty( "foo" )]
    public String Foo { get; }
    
    [JsonProperty( "bar" )]
    public Int32 Bar { get; }
}

Screenshot proof:

enter image description here

Nevski answered 6/3 at 7:47 Comment(0)
K
-1

It is handled under JsonReaderException

catch (JsonReaderException ex) 
{
  //handle your exception here
}
Kinship answered 23/8, 2022 at 13:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.