a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
172 lines
12 KiB
HTML
172 lines
12 KiB
HTML
<html>
|
|
|
|
<head>
|
|
<title>Serialization Error Handling</title>
|
|
<link href="styles.css" rel="stylesheet" type="text/css" />
|
|
<link href="custom.css" rel="stylesheet" type="text/css" />
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div id="control">
|
|
<span class="productTitle">Json.NET - Quick Starts & API Documentation</span><br />
|
|
<span class="topicTitle">Serialization Error Handling</span></div>
|
|
|
|
<div id="content">
|
|
<span style="color: DarkGray"> </span>
|
|
|
|
<p>Json.NET supports error handling during serialization and deserialization. Error handling lets
|
|
you catch an error and choose whether to handle it and continue with serialization or let the error
|
|
bubble up and be thrown in your application.</p>
|
|
<p>Error handling is defined through two methods:
|
|
the Error event on JsonSerializer and the OnErrorAttribute.</p>
|
|
<h3>Error Event</h3>
|
|
|
|
<p>
|
|
The <a href="./html/E_Newtonsoft_Json_JsonSerializer_Error.htm">Error</a> event is an event handler found on <a href="./html/T_Newtonsoft_Json_JsonSerializer.htm">JsonSerializer</a>. The error event is raised whenever an
|
|
exception is thrown while serializing or deserialing JSON. Like all settings found on JsonSerializer
|
|
it can also be set on <a href="./html/T_Newtonsoft_Json_JsonSerializer.htm">JsonSerializerSettings</a> and passed to the serialization methods on JsonConvert.</p>
|
|
|
|
<div class="overflowpanel"> <div class="code">
|
|
<div style="font-family: Courier New; font-size: 10pt; color: black;">
|
|
<pre style="margin: 0px;"><span style="color: #2b91af;">List</span><<span style="color: blue;">string</span>> errors = <span style="color: blue;">new</span> <span style="color: #2b91af;">List</span><<span style="color: blue;">string</span>>();</pre>
|
|
<pre style="margin: 0px;"> </pre>
|
|
<pre style="margin: 0px;"><span style="color: #2b91af;">List</span><<span style="color: #2b91af;">DateTime</span>> c = <span style="color: #2b91af;">JsonConvert</span>.DeserializeObject<<span style="color: #2b91af;">List</span><<span style="color: #2b91af;">DateTime</span>>>(<span style="color: #a31515;">@"[</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: #a31515;"> ""2009-09-09T00:00:00Z"",</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: #a31515;"> ""I am not a date and will error!"",</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: #a31515;"> [</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: #a31515;"> 1</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: #a31515;"> ],</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: #a31515;"> ""1977-02-20T00:00:00Z"",</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: #a31515;"> null,</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: #a31515;"> ""2000-12-01T00:00:00Z""</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: #a31515;">]"</span>,</pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">new</span> <span style="color: #2b91af;">JsonSerializerSettings</span></pre>
|
|
<pre style="margin: 0px;"> {</pre>
|
|
<pre style="margin: 0px;"> Error = <span style="color: blue;">delegate</span>(<span style="color: blue;">object</span> sender, <span style="color: #2b91af;">ErrorEventArgs</span> args)</pre>
|
|
<pre style="margin: 0px;"> {</pre>
|
|
<pre style="margin: 0px;"> errors.Add(args.ErrorContext.Error.Message);</pre>
|
|
<pre style="margin: 0px;"> args.ErrorContext.Handled = <span style="color: blue;">true</span>;</pre>
|
|
<pre style="margin: 0px;"> },</pre>
|
|
<pre style="margin: 0px;"> Converters = { <span style="color: blue;">new</span> <span style="color: #2b91af;">IsoDateTimeConverter</span>() }</pre>
|
|
<pre style="margin: 0px;"> });</pre>
|
|
<pre style="margin: 0px;"> </pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">// 2009-09-09T00:00:00Z</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">// 1977-02-20T00:00:00Z</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">// 2000-12-01T00:00:00Z</span></pre>
|
|
<pre style="margin: 0px;"> </pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">// The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">// Unexpected token parsing date. Expected String, got StartArray.</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">// Cannot convert null value to System.DateTime.</span></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p>
|
|
In this example we are deserializing a JSON array to a collection of DateTimes. On the JsonSerializerSettings
|
|
a handler has been assigned to the Error event which will log the error message and mark the error as handled.
|
|
</p>
|
|
<p>
|
|
The result of deserializing the JSON is three successfully deserialized dates and three error messages:
|
|
one for the badly formatted string, "I am not a date and will error!", one for the nested JSON array and one
|
|
for the null value since the list doesn't allow nullable DateTimes. The event handler has logged these messages
|
|
and Json.NET has continued on deserializing the JSON because the errors were marked as handled.
|
|
</p>
|
|
<p>
|
|
One thing to note with error handling in Json.NET is that an unhandled error will bubble up and raise the event
|
|
on each of its parents, e.g. an unhandled error when serializing a collection of objects will be raised twice,
|
|
once against the object and then again on the collection. This will let you handle an error either where it
|
|
occurred or on one of its parents.
|
|
</p>
|
|
|
|
|
|
<div class="overflowpanel"> <div class="code">
|
|
<div style="font-family: Courier New; font-size: 10pt; color: black;">
|
|
<pre style="margin: 0px;"><span style="color: #2b91af;">JsonSerializer</span> serializer = <span style="color: blue;">new</span> <span style="color: #2b91af;">JsonSerializer</span>();</pre>
|
|
<pre style="margin: 0px;">serializer.Error += <span style="color: blue;">delegate</span>(<span style="color: blue;">object</span> sender, <span style="color: #2b91af;">ErrorEventArgs</span> args)</pre>
|
|
<pre style="margin: 0px;"> {</pre>
|
|
<pre style="margin: 0px;"> <span style="color: green;">// only log an error once</span></pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">if</span> (args.CurrentObject == args.ErrorContext.OriginalObject)</pre>
|
|
<pre style="margin: 0px;"> errors.Add(args.ErrorContext.Error.Message);</pre>
|
|
<pre style="margin: 0px;"> };</pre>
|
|
</div>
|
|
</div></div>
|
|
|
|
<p>If you aren't immediately handling an error and only want to perform an action against it once then
|
|
you can check to see whether the <a href="./html/T_Newtonsoft_Json_Serialization_ErrorEventArgs.htm">ErrorEventArg</a>'s CurrentObject is equal to the OriginalObject.
|
|
OriginalObject is the object that threw the error and CurrentObject is the object that the event is being raised
|
|
against. They will only equal the first time the event is raised against the OriginalObject.</p>
|
|
|
|
<h3>OnErrorAttribute</h3>
|
|
|
|
<p>
|
|
The <a href="./html/T_Newtonsoft_Json_Serialization_OnErrorAttribute.htm">OnErrorAttribute</a> works much like the other <a href="SerializationCallbacks.html">.NET serialization attributes</a> that Json.NET supports.
|
|
To use it you simply place the attribute on a method which takes the correct parameters: a StreamingContext and a ErrorContext.
|
|
The name of the method doesn't matter. </p>
|
|
<div class="overflowpanel"> <div class="code">
|
|
|
|
<div style="font-family: Courier New; font-size: 10pt; color: black;">
|
|
<pre style="margin: 0px;"><span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">PersonError</span></pre>
|
|
<pre style="margin: 0px;">{</pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">private</span> <span style="color: #2b91af;">List</span><<span style="color: blue;">string</span>> _roles;</pre>
|
|
<pre style="margin: 0px;"> </pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;">string</span> Name { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;">int</span> Age { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: #2b91af;">List</span><<span style="color: blue;">string</span>> Roles</pre>
|
|
<pre style="margin: 0px;"> {</pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">get</span></pre>
|
|
<pre style="margin: 0px;"> {</pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">if</span> (_roles == <span style="color: blue;">null</span>)</pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">throw</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">Exception</span>(<span style="color: #a31515;">"Roles not loaded!"</span>);</pre>
|
|
<pre style="margin: 0px;"> </pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">return</span> _roles;</pre>
|
|
<pre style="margin: 0px;"> }</pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">set</span> { _roles = <span style="color: blue;">value</span>; }</pre>
|
|
<pre style="margin: 0px;"> }</pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;">string</span> Title { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</pre>
|
|
<pre style="margin: 0px;"> </pre>
|
|
<pre style="margin: 0px;"> [<span style="color: #2b91af;">OnError</span>]</pre>
|
|
<pre style="margin: 0px;"> <span style="color: blue;">internal</span> <span style="color: blue;">void</span> OnError(<span style="color: #2b91af;">StreamingContext</span> context, <span style="color: #2b91af;">ErrorContext</span> errorContext)</pre>
|
|
<pre style="margin: 0px;"> {</pre>
|
|
<pre style="margin: 0px;"> errorContext.Handled = <span style="color: blue;">true</span>;</pre>
|
|
<pre style="margin: 0px;"> }</pre>
|
|
<pre style="margin: 0px;">}</pre>
|
|
</div>
|
|
</div></div>
|
|
<p>
|
|
In this example accessing the the Roles property will throw an exception when no roles have
|
|
been set. The HandleError method will set the error when serializing Roles as handled and allow Json.NET to continue
|
|
serializing the class.
|
|
</p>
|
|
|
|
<div class="overflowpanel"> <div class="code">
|
|
<div style="font-family: Courier New; font-size: 10pt; color: black;">
|
|
<pre style="margin: 0px;"><span style="color: #2b91af;">PersonError</span> person = <span style="color: blue;">new</span> <span style="color: #2b91af;">PersonError</span></pre>
|
|
<pre style="margin: 0px;"> {</pre>
|
|
<pre style="margin: 0px;"> Name = <span style="color: #a31515;">"George Michael Bluth"</span>,</pre>
|
|
<pre style="margin: 0px;"> Age = 16,</pre>
|
|
<pre style="margin: 0px;"> Roles = <span style="color: blue;">null</span>,</pre>
|
|
<pre style="margin: 0px;"> Title = <span style="color: #a31515;">"Mister Manager"</span></pre>
|
|
<pre style="margin: 0px;"> };</pre>
|
|
<pre style="margin: 0px;"> </pre>
|
|
<pre style="margin: 0px;"><span style="color: blue;">string</span> json = <span style="color: #2b91af;">JsonConvert</span>.SerializeObject(person, <span style="color: #2b91af;">Formatting</span>.Indented);</pre>
|
|
<pre style="margin: 0px;"> </pre>
|
|
<pre style="margin: 0px;"><span style="color: #2b91af;">Console</span>.WriteLine(json);</pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">//{</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">// "Name": "George Michael Bluth",</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">// "Age": 16,</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">// "Title": "Mister Manager"</span></pre>
|
|
<pre style="margin: 0px;"><span style="color: green;">//}</span></pre>
|
|
</div>
|
|
</div></div>
|
|
|
|
|
|
<div id="footer">
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</body>
|
|
|
|
</html> |