Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JsonSerializationException Parsing

Tags:

c#

json.net

I'm trying to wrap my application with some graceful exception handling. When my app fails to deserialize JSON, I get a JsonSerializationException that has a Message that looks like this:

Error converting value "[IncorrectDataType]" to type 'ApexFramework.Enums+DataTypes'. Path 'Layout[0].ElementContainer[0].ContainerDatatype', line 12, position 58.

From this exception message, I am interested in capturing and presenting in a clean manner the following:

  • I need the Index of the Element Container in Layout[] (this would be 0 from the above example)
  • I need the Index of the ContainerDataType in ElementContainer[] (this would be 0 from the above example)

I looked through the

JsonSerializationException

object and there is nothing that I grab with ease, so:

Can anyone confirm that there is no way to work with the JsonSerializationException to get the info I need in a clean manner?

If not, can anyone help me come up with the most elegant and efficient way to grab the info I need from the exception stack?

like image 878
dataauto_mation Avatar asked Nov 29 '25 10:11

dataauto_mation


1 Answers

You can use Json.NET's serialization error event handling functionality to get information about the exception in a somewhat more useful format.

When an exception during deserialization occurs, Json.NET catches and re-throws it at each level in the object hierarchy, giving each object an opportunity to handle the exception using an OnError method. While you don't want to handle the exception, you can take advantage of this to record details about where the exception occurred via the information provided in the ErrorEventArgs passed to the JsonSerializerSettings.Error event handler. For instance, the following code captures and reports the path at which the exception occurred, the member causing the exception, and the stack of objects being deserialized at when the error was encountered:

static bool TryDeserialize<TRootObject>(string jsonString, out TRootObject root)
{
    var errorStack = new Stack<Newtonsoft.Json.Serialization.ErrorEventArgs>();
    var settings = new JsonSerializerSettings
    {
        Converters = { new StringEnumConverter() },
        Error = (o, e) => errorStack.Push(e)
    };
    try
    {
        root = JsonConvert.DeserializeObject<TRootObject>(jsonString, settings);
        return true;
    }
    catch (JsonException ex)
    {
        var last = errorStack.Last();
        var member = last.ErrorContext.Member;
        var path = last.ErrorContext.Path;
        var objectsStack = String.Join(", ", errorStack
                                       .Where(e => e.CurrentObject != null)
                                       .Select(e => e.CurrentObject.ToString()));

        Console.WriteLine("Exception parsing JSON: ");
        Console.WriteLine(ex.Message);
        Console.WriteLine("Error context details: ");
        Console.WriteLine("   Path: {0}\n   Member: {1}\n   Object stack = {{{2}}}", 
                          path, member, objectsStack);
        root = default(TRootObject);
        return false;
    }
}

Then, if I attempt to deserialize JSON into the data model implied by your question, I get the following error messages:

Exception parsing JSON: 
Error converting value "[IncorrectDataType]" to type 'DataTypes'. Path 'Layout[0].ElementContainer[0].ContainerDatatype', line 6, position 56.
Error context details: 
   Path: Layout[0].ElementContainer[0].ContainerDatatype
   Member: ContainerDatatype
   Object stack = {RootObject, System.Collections.Generic.List`1[Layout], Layout, System.Collections.Generic.List`1[ElementContainer], ElementContainer}

As you can see, the information you need is more cleanly available, so that you will no longer need to parse the exception message. You will still need to parse the exception path to extract the indices, however the path syntax is standard JSONPath syntax and so is well-defined. You could model your path parsing code on any pre-existing JSONPath parser including Json.NET's own JPath.

Notes:

  • I don't particularly recommend handling the exception and continuing, since error handling in Json.NET is reported to be "very flaky" by Newtonsoft.

Sample working .Net fiddle here.

like image 105
dbc Avatar answered Dec 02 '25 01:12

dbc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!