-Added documentation (gasp!)
-Fixed serialization of Uri members on Silverlight/Compact Framework -Fixed serialization of JToken members -Fixed (hopefully) cache threading issues
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Advanced JSON Serialization</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">Advanced JSON Serialization</span></div>
|
||||
|
||||
<div id="content">
|
||||
<span style="color: DarkGray"> </span>
|
||||
|
||||
<p>The Json.NET serializer has a number of advanced options to alter how JSON is serialized and deserialized.</p>
|
||||
|
||||
<h3>IMappingResolver</h3>
|
||||
|
||||
<p>The <a href="./html/T_Newtonsoft_Json_Serialization_IMappingResolver.htm">IMappingResolver</a> interface provides a way to globally customize how the JsonSerializer maps JSON properties to .NET object members.</p>
|
||||
<p>Implementing the IMappingResolver interface and then assigning an instance to a JsonSerializer lets you control what object members should be serialized, how they are serialized and what they are called.</p>
|
||||
|
||||
<h4>DefaultMappingResolver</h4>
|
||||
<p>The <a href="./html/T_Newtonsoft_Json_Serialization_DefaultMappingResolver.htm">DefaultMappingResolver</a> is the default resolver used by the serializer. It provides many avenues of extensibility in the form of virtual methods that can be overriden.</p>
|
||||
|
||||
<h4>CamelCaseMappingResolver</h4>
|
||||
<p><a href="./html/T_Newtonsoft_Json_Serialization_CamelCaseMappingResolver.htm">CamelCaseMappingResolver</a> inherits from DefaultMappingResolver and simply overrides the JSON property name to be written in <a href="http://en.wikipedia.org/wiki/CamelCase" target="_blank">camelcase</a>.</p>
|
||||
|
||||
<div class="overflowpanel"> <div class="code"> <div style="font-family: courier new; color: black; font-size: 10pt;"> <pre style="margin: 0px;"><span style="color: rgb(43, 145, 175);">Product</span> product = <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">Product</span></pre>
|
||||
|
||||
<pre style="margin: 0px;"> {</pre>
|
||||
|
||||
<pre style="margin: 0px;"> ExpiryDate = <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">DateTime</span>(2010, 12, 20, 18, 1, 0, <span style="color: rgb(43, 145, 175);">DateTimeKind</span>.Utc),</pre>
|
||||
|
||||
<pre style="margin: 0px;"> Name = <span style="color: rgb(163, 21, 21);">"Widget"</span>,</pre>
|
||||
|
||||
<pre style="margin: 0px;"> Price = 9.99m,</pre>
|
||||
|
||||
<pre style="margin: 0px;"> Sizes = <span style="color: blue;">new</span>[] {<span style="color: rgb(163, 21, 21);">"Small"</span>, <span style="color: rgb(163, 21, 21);">"Medium"</span>, <span style="color: rgb(163, 21, 21);">"Large"</span>}</pre>
|
||||
|
||||
<pre style="margin: 0px;"> };</pre>
|
||||
|
||||
<pre style="margin: 0px;"> </pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: blue;">string</span> json = </pre>
|
||||
|
||||
<pre style="margin: 0px;"> <span style="color: rgb(43, 145, 175);">JsonConvert</span>.SerializeObject(</pre>
|
||||
|
||||
<pre style="margin: 0px;"> product,</pre>
|
||||
|
||||
<pre style="margin: 0px;"> <span style="color: rgb(43, 145, 175);">Formatting</span>.Indented,</pre>
|
||||
|
||||
<pre style="margin: 0px;"> <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">JsonSerializerSettings</span> { MappingResolver = <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">CamelCaseMappingResolver</span>() }</pre>
|
||||
|
||||
<pre style="margin: 0px;"> );</pre>
|
||||
|
||||
<pre style="margin: 0px;"> </pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: green;">//{</span></pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: green;">// "name": "Widget",</span></pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: green;">// "expiryDate": "\/Date(1292868060000)\/",</span></pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: green;">// "price": 9.99,</span></pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: green;">// "sizes": [</span></pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: green;">// "Small",</span></pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: green;">// "Medium",</span></pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: green;">// "Large"</span></pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: green;">// ]</span></pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: green;">//}</span></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,94 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Serializing Dates in JSON</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">Serializing Dates in JSON</span></div>
|
||||
|
||||
<div id="content">
|
||||
<span style="color: DarkGray"> </span>
|
||||
<p>DateTimes in JSON are hard.</p>
|
||||
<p>
|
||||
The problem comes from the <a href="http://www.ietf.org/rfc/rfc4627.txt" target="_blank">JSON spec</a> itself, there is no literal syntax for dates in JSON. The spec has objects, arrays, strings, integers and floats, but it defines no standard for what a date looks like.</p>
|
||||
<p>The default format used by <a href="http://james.newtonking.com/projects/json-net.aspx" target="_blank">Json.NET</a> for dates is the same one used by Microsoft: "\/Date(1198908717056)\/". You can read more about it <a href="http://weblogs.asp.net/bleroy/archive/2008/01/18/dates-and-json.aspx" target="_blank">here</a>.</p>
|
||||
|
||||
<h3>DateTime JsonConverters</h3>
|
||||
<p>With no standard for dates in JSON, the number of possible different formats when interoping with other systems is endless. Fortunately Json.NET has a solution to deal with reading and writing custom dates: JsonConverters. A JsonConverter is used to override how a type is serialized.</p>
|
||||
|
||||
<div class="overflowpanel">
|
||||
<div class="code">
|
||||
<div style="font-size: 10pt; color: black; font-family: courier new;">
|
||||
<pre style="margin: 0px;"><span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: rgb(43, 145, 175);">LogEntry</span></pre>
|
||||
<pre style="margin: 0px;">{</pre>
|
||||
<pre style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;">string</span> Details { <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: rgb(43, 145, 175);">DateTime</span> LogDate { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</pre>
|
||||
<pre style="margin: 0px;">}</pre>
|
||||
<pre style="margin: 0px;"> </pre>
|
||||
<pre style="margin: 0px;">[<span style="color: rgb(43, 145, 175);">Test</span>]</pre>
|
||||
|
||||
<pre style="margin: 0px;"><span style="color: blue;">public</span> <span style="color: blue;">void</span> WriteJsonDates()</pre>
|
||||
<pre style="margin: 0px;">{</pre>
|
||||
<pre style="margin: 0px;"> <span style="color: rgb(43, 145, 175);">LogEntry</span> entry = <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">LogEntry</span></pre>
|
||||
<pre style="margin: 0px;"> {</pre>
|
||||
|
||||
<pre style="margin: 0px;"> LogDate = <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">DateTime</span>(2009, 2, 15, 0, 0, 0, <span style="color: rgb(43, 145, 175);">DateTimeKind</span>.Utc),</pre>
|
||||
<pre style="margin: 0px;"> Details = <span style="color: rgb(163, 21, 21);">"Application started."</span></pre>
|
||||
<pre style="margin: 0px;"> };</pre>
|
||||
<pre style="margin: 0px;"> </pre>
|
||||
|
||||
<pre style="margin: 0px;"> <span style="color: blue;">string</span> defaultJson = <span style="color: rgb(43, 145, 175);">JsonConvert</span>.SerializeObject(entry);</pre>
|
||||
<pre style="margin: 0px;"> <span style="color: green;">// {"Details":"Application started.","LogDate":"\/Date(1234656000000)\/"}</span></pre>
|
||||
<pre style="margin: 0px;"></pre>
|
||||
<pre style="margin: 0px;"> </pre>
|
||||
<pre style="margin: 0px;"> <span style="color: blue;">string</span> javascriptJson = <span style="color: rgb(43, 145, 175);">JsonConvert</span>.SerializeObject(entry, <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">JavaScriptDateTimeConverter</span>());</pre>
|
||||
|
||||
<pre style="margin: 0px;"> <span style="color: green;">// {"Details":"Application started.","LogDate":new Date(1234656000000)}</span></pre>
|
||||
<pre style="margin: 0px;"> </pre>
|
||||
<pre style="margin: 0px;"> <span style="color: blue;">string</span> isoJson = <span style="color: rgb(43, 145, 175);">JsonConvert</span>.SerializeObject(entry, <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">IsoDateTimeConverter</span>());</pre>
|
||||
<pre style="margin: 0px;"> <span style="color: green;">// {"Details":"Application started.","LogDate":"2009-02-15T00:00:00Z"}</span></pre>
|
||||
|
||||
<pre style="margin: 0px;">}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Simply pass the JsonConverter you wish to use to the Json.NET serializer.</p>
|
||||
<h4>JavaScriptDateTimeConverter</h4>
|
||||
<p>The JavaScriptDateTimeConverter class is one of the two DateTime JsonConverters that come with Json.NET. This converter serializes a DateTime as a <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date" target="_blank">JavaScript Date object</a>.</p>
|
||||
<div class="overflowpanel">
|
||||
<div class="code">
|
||||
<div style="font-size: 10pt; color: black; font-family: courier new;">
|
||||
<pre style="margin: 0px;">new Date(1234656000000)</pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Technically this is invalid JSON according to the spec but all browsers, and some JSON frameworks including Json.NET, support it. </p>
|
||||
<h4>IsoDateTimeConverter</h4>
|
||||
<p>IsoDateTimeConverter seralizes a DateTime to an <a href="http://en.wikipedia.org/wiki/ISO_8601" target="_blank">ISO 8601</a> formatted string.</p>
|
||||
<div class="overflowpanel">
|
||||
<div class="code">
|
||||
<div style="font-size: 10pt; color: black; font-family: courier new;">
|
||||
<pre style="margin: 0px;"><span style="color: rgb(163, 21, 21);">"2009-02-15T00:00:00Z"</span></pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The IsoDateTimeConverter class has a property, DateTimeFormat, to further customize the formatted string.</p>
|
||||
<p> </p>
|
||||
<p>One final thing to note is all date values returned by Json.NET are in <a href="http://en.wikipedia.org/wiki/Utc" target="_blank">UTC time</a>.</p>
|
||||
|
||||
|
||||
<div id="footer"></div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -15,7 +15,7 @@
|
||||
<div id="content">
|
||||
<span style="color: DarkGray"> </span>
|
||||
|
||||
<p>To manually read and write JSON Json.NET provides the <a href="./html/T_Newtonsoft_Json_JsonReader.htm>JsonReader</a> and <a href="./html/T_Newtonsoft_Json_JsonWriter.htm">JsonWriter</a> classes.</p>
|
||||
<p>To manually read and write JSON Json.NET provides the <a href="./html/T_Newtonsoft_Json_JsonReader.htm">JsonReader</a> and <a href="./html/T_Newtonsoft_Json_JsonWriter.htm">JsonWriter</a> classes.</p>
|
||||
|
||||
<h3>JsonTextReader and JsonTextWriter</h3>
|
||||
<p><a href="./html/T_Newtonsoft_Json_JsonTextReader.htm">JsonTextReader</a> and <a href="./html/T_Newtonsoft_Json_JsonTextWriter.htm">JsonTextWriter</a> are used to read and write JSON text. The JsonTextWriter has a number of settings on it to control how JSON is formatted when it is written. These options include formatting, indention character, indent count and quote character.</p>
|
||||
@@ -60,7 +60,7 @@
|
||||
</div></div>
|
||||
|
||||
<h3>JTokenReader and JTokenWriter</h3>
|
||||
<p><a href="./html/T_Newtonsoft_Json_JTokenReader.htm">JTokenReader</a> and <a href="./html/T_Newtonsoft_Json_JTokenWriter.htm">JTokenWriter</a> read and write LINQ to JSON objects. They are located in the <a href="./html/N_Newtonsoft_Json_Linq.htm">Newtonsoft.Json.Linq</a> namespace. These objects allow you to use LINQ to JSON objects with objects that read and write JSON such as the JsonSerializer. For example you can deserialize from a LINQ to JSON object into a regular .NET object and vice versa.</p>
|
||||
<p><a href="./html/T_Newtonsoft_Json_Linq_JTokenReader.htm">JTokenReader</a> and <a href="./html/T_Newtonsoft_Json_Linq_JTokenWriter.htm">JTokenWriter</a> read and write LINQ to JSON objects. They are located in the <a href="./html/N_Newtonsoft_Json_Linq.htm">Newtonsoft.Json.Linq</a> namespace. These objects allow you to use LINQ to JSON objects with objects that read and write JSON such as the JsonSerializer. For example you can deserialize from a LINQ to JSON object into a regular .NET object and vice versa.</p>
|
||||
|
||||
<div class="overflowpanel"> <div class="code">
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<pre style="margin: 0px;"><span style="color: green;">// ]</span></pre>
|
||||
<pre style="margin: 0px;"><span style="color: green;">//}</span></pre>
|
||||
<pre style="margin: 0px;"> </pre>
|
||||
<pre style="margin: 0px;"><span style="color: #2b91af;">Product</span> deserializedProduct = (<span style="color: #2b91af;">Product</span>)<span style="color: #2b91af;">JsonConvert</span>.DeserializeObject(output, <span style="color: blue;">typeof</span>(<span style="color: #2b91af;">Product</span>));</pre>
|
||||
<pre style="margin: 0px;"><span style="color: #2b91af;">Product</span> deserializedProduct = <span style="color: #2b91af;">JsonConvert</span>.DeserializeObject<<span style="color: #2b91af;">Product</span>>(output);</pre>
|
||||
</div>
|
||||
|
||||
</div></div>
|
||||
@@ -95,8 +95,14 @@ the member's DefaultValueAttribute. Include or ignore.</p>
|
||||
<h5>Converters</h5>
|
||||
<p>A collection of JsonConverters that will be used during serialization and
|
||||
deserialization.</p>
|
||||
<h5>TypeNameHandling</h5>
|
||||
<p>Controls how .NET type names are used when serializing and deserializing JSON. If
|
||||
type names are SDFSDFSDF</p>
|
||||
<h3>Serialization Attributes</h3>
|
||||
<p>There are a number of attributes that can be placed on a class to control how it is serialized.</p>
|
||||
<p>Note that as well as using the built-in Json.NET attributes, Json.NET also looks for the
|
||||
<a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx" target="_blank">DataContract</a> and
|
||||
<a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx" target="_blank">DataMember</a> attributes when determining how JSON is to be serialized and deserialized. If both are present the Json.NET serialization attributes take precedence.</p>
|
||||
|
||||
<div class="overflowpanel"> <div class="code">
|
||||
|
||||
@@ -144,17 +150,31 @@ finally any converters passed to the JsonSerializer.</p>
|
||||
|
||||
|
||||
|
||||
<h5>IsoDateTimeConverter</h5>
|
||||
<p>Converts a DateTime to and from the ISO 8601 date format (e.g. 2008-04-12T12:53Z).</p>
|
||||
|
||||
<h5>JavaScriptDateTimeConverter</h5>
|
||||
<p>Converts a DateTime to and from a JavaScript date constructor (e.g. new Date(52231943)).</p>
|
||||
<h5>DateTime JSON Converters</h5>
|
||||
<p>Json.NET comes with a number of JsonConverters for serializing and deserializing DateTimes. Read
|
||||
more about dates and Json.NET <a href="DatesInJSON.html">here</a>.</p>
|
||||
|
||||
<h5>XmlNodeConverter</h5>
|
||||
<p>Converts an XmlNode to and from JSON. Note that to convert a JSON object it must have only a single property. This is required because properties are converted into nodes and XML can only have one root node.</p>
|
||||
<p>Converts an XmlNode to and from JSON. Note that to convert a JSON object it must have only a single property
|
||||
or you must define a root node name to be inserted when using this converter. This is required because properties are converted into nodes and
|
||||
well formed XML can only have one root node.</p>
|
||||
|
||||
|
||||
<div id="footer"></div>
|
||||
<h5>BinaryConverter</h5>
|
||||
<p>Converts binary data like a byte array or SqlBinary object to JSON. The binary
|
||||
data is encoded in Base64.</p>
|
||||
|
||||
<h5>CustomCreationConverter</h5>
|
||||
<p>An abstract JsonConverter for customizing how an object is create during deserialization.
|
||||
Inherit from this class and implement the Create method with your own code to create and return an object.
|
||||
The object will then be populated with JSON values by the serializer.</p>
|
||||
<p>A possible example of using this converter would be to call out to a dependency injection framework to resolve what object should be created</p>
|
||||
|
||||
<div id="footer">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
<contentItem sourcePath=".\LINQtoJSON.html" destPath="" excludeItems="False" />
|
||||
<contentItem sourcePath=".\ReadingWritingJSON.html" destPath="" excludeItems="False" />
|
||||
<contentItem sourcePath=".\donate.gif" destPath="" excludeItems="False" />
|
||||
<contentItem sourcePath=".\AdvanceSerializingJSON.html" destPath="" excludeItems="False" />
|
||||
<contentItem sourcePath=".\DatesInJSON.html" destPath="" excludeItems="False" />
|
||||
</additionalContent>
|
||||
<ProjectSummary />
|
||||
<MissingTags>Summary, Parameter, Returns, AutoDocumentCtors, Namespace, TypeParameter</MissingTags>
|
||||
|
||||
+5
-2
@@ -1,7 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
|
||||
<siteMapNode title="Introduction" url=".\Introduction.html" isDefault="true" />
|
||||
<siteMapNode title="Serializing and deserializing JSON" url=".\SerializingJSON.html" />
|
||||
<siteMapNode title="Serializing and deserializing JSON" url=".\SerializingJSON.html">
|
||||
<siteMapNode title="Advanced JSON serialization" url=".\AdvanceSerializingJSON.html" />
|
||||
<siteMapNode title="Serializing dates in JSON" url=".\DatesInJSON.html" />
|
||||
</siteMapNode>
|
||||
<siteMapNode title="LINQ to JSON" url=".\LINQtoJSON.html" />
|
||||
<siteMapNode title="Reading and Writing JSON" url=".\ReadingWritingJSON.html" />
|
||||
<siteMapNode title="Reading and writing JSON" url=".\ReadingWritingJSON.html" />
|
||||
</siteMap>
|
||||
@@ -2573,5 +2573,55 @@ keyword such as type of business.""
|
||||
Assert.AreEqual("Medium", deserializedProduct.Sizes[1]);
|
||||
Assert.AreEqual("Large", deserializedProduct.Sizes[2]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NestedInsideOuterObject()
|
||||
{
|
||||
string json = @"{
|
||||
""short"": {
|
||||
""original"": ""http://www.contrast.ie/blog/online-marketing-2009/"",
|
||||
""short"": ""m2sqc6"",
|
||||
""shortened"": ""http://short.ie/m2sqc6"",
|
||||
""error"": {
|
||||
""code"": 0,
|
||||
""msg"": ""No action taken""
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
JObject o = JObject.Parse(json);
|
||||
|
||||
Shortie s = JsonConvert.DeserializeObject<Shortie>(o["short"].ToString());
|
||||
Assert.IsNotNull(s);
|
||||
|
||||
Assert.AreEqual(s.Original, "http://www.contrast.ie/blog/online-marketing-2009/");
|
||||
Assert.AreEqual(s.Short, "m2sqc6");
|
||||
Assert.AreEqual(s.Shortened, "http://short.ie/m2sqc6");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UriSerialization()
|
||||
{
|
||||
Uri uri = new Uri("http://codeplex.com");
|
||||
string json = JsonConvert.SerializeObject(uri);
|
||||
|
||||
Assert.AreEqual("http://codeplex.com/", uri.ToString());
|
||||
|
||||
Uri newUri = JsonConvert.DeserializeObject<Uri>(json);
|
||||
Assert.AreEqual(uri, newUri);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AnonymousPlusLinqToSql()
|
||||
{
|
||||
var value = new
|
||||
{
|
||||
bar = new JObject(new JProperty("baz", 13))
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
|
||||
Assert.AreEqual(@"{""bar"":{""baz"":13}}", json);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,5 +454,37 @@ Parameter name: arrayIndex")]
|
||||
Console.WriteLine(name);
|
||||
Console.WriteLine(smallest);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void sdfs()
|
||||
{
|
||||
string jsonText = @"{
|
||||
""short"":{
|
||||
""original"":""http://www.foo.com/"",
|
||||
""short"":""krehqk"",
|
||||
""error"":{
|
||||
""code"":0,
|
||||
""msg"":""No action taken""}
|
||||
}";
|
||||
|
||||
JObject json = JObject.Parse(jsonText);
|
||||
|
||||
Shortie shortie = new Shortie
|
||||
{
|
||||
Original = (string)json["short"]["original"],
|
||||
Short = (string)json["short"]["short"],
|
||||
Error = new ShortieException
|
||||
{
|
||||
Code = (int)json["short"]["error"]["code"],
|
||||
ErrorMessage = (string)json["short"]["error"]["msg"]
|
||||
}
|
||||
};
|
||||
|
||||
Assert.AreEqual("http://www.foo.com/", shortie.Original);
|
||||
Assert.AreEqual("krehqk", shortie.Short);
|
||||
Assert.AreEqual(null, shortie.Shortened);
|
||||
Assert.AreEqual(0, shortie.Error.Code);
|
||||
Assert.AreEqual("No action taken", shortie.Error.ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
<Compile Include="TestObjects\Product.cs" />
|
||||
<Compile Include="TestObjects\ProductCollection.cs" />
|
||||
<Compile Include="TestObjects\ProductShort.cs" />
|
||||
<Compile Include="TestObjects\Shortie.cs" />
|
||||
<Compile Include="TestObjects\Store.cs" />
|
||||
<Compile Include="TestObjects\StoreColor.cs" />
|
||||
<Compile Include="TestObjects\Person.cs" />
|
||||
|
||||
@@ -114,6 +114,7 @@
|
||||
<Compile Include="TestObjects\Product.cs" />
|
||||
<Compile Include="TestObjects\ProductCollection.cs" />
|
||||
<Compile Include="TestObjects\ProductShort.cs" />
|
||||
<Compile Include="TestObjects\Shortie.cs" />
|
||||
<Compile Include="TestObjects\Store.cs" />
|
||||
<Compile Include="TestObjects\StoreColor.cs" />
|
||||
<Compile Include="TestObjects\Person.cs" />
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
<Compile Include="TestObjects\Product.cs" />
|
||||
<Compile Include="TestObjects\ProductCollection.cs" />
|
||||
<Compile Include="TestObjects\ProductShort.cs" />
|
||||
<Compile Include="TestObjects\Shortie.cs" />
|
||||
<Compile Include="TestObjects\Store.cs" />
|
||||
<Compile Include="TestObjects\StoreColor.cs" />
|
||||
<Compile Include="TestObjects\Person.cs" />
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.TestObjects
|
||||
{
|
||||
[XmlRoot("short")]
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class Shortie
|
||||
{
|
||||
[JsonProperty("original")]
|
||||
[XmlElement("original")]
|
||||
public String Original { get; set; }
|
||||
|
||||
[JsonProperty("shortened")]
|
||||
[XmlElement("shortened")]
|
||||
public String Shortened { get; set; }
|
||||
|
||||
[JsonProperty("short")]
|
||||
[XmlElement("short")]
|
||||
public String Short { get; set; }
|
||||
|
||||
public ShortieException Error { get; set; }
|
||||
}
|
||||
|
||||
public class ShortieException
|
||||
{
|
||||
[JsonProperty("code")]
|
||||
[XmlElement("code")]
|
||||
public int Code { get; set; }
|
||||
|
||||
[JsonProperty("msg")]
|
||||
[XmlElement("msg")]
|
||||
public String ErrorMessage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Newtonsoft.Json.Tests", "Ne
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doc", "Doc", "{8F9E13D9-4181-4BA6-8802-EB5B3EB9445A}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Doc\AdvanceSerializingJSON.html = Doc\AdvanceSerializingJSON.html
|
||||
Doc\custom.css = Doc\custom.css
|
||||
Doc\DatesInJSON.html = Doc\DatesInJSON.html
|
||||
Doc\doc.shfb = Doc\doc.shfb
|
||||
Doc\doc.sitemap = Doc\doc.sitemap
|
||||
Doc\donate.gif = Doc\donate.gif
|
||||
|
||||
@@ -135,6 +135,7 @@
|
||||
<Compile Include="Serialization\JsonSerializerReader.cs" />
|
||||
<Compile Include="Serialization\JsonSerializerWriter.cs" />
|
||||
<Compile Include="Serialization\JsonTypeReflector.cs" />
|
||||
<Compile Include="Serialization\ThreadSafeDictionaryWrapper.cs" />
|
||||
<Compile Include="TypeNameHandling.cs" />
|
||||
<Compile Include="Utilities\BidirectionalDictionary.cs" />
|
||||
<Compile Include="Utilities\ConvertUtils.cs" />
|
||||
|
||||
@@ -113,6 +113,7 @@
|
||||
<Compile Include="Serialization\JsonSerializerProxy.cs" />
|
||||
<Compile Include="Serialization\JsonSerializerReader.cs" />
|
||||
<Compile Include="Serialization\JsonSerializerWriter.cs" />
|
||||
<Compile Include="Serialization\ThreadSafeDictionaryWrapper.cs" />
|
||||
<Compile Include="TypeNameHandling.cs" />
|
||||
<Compile Include="Utilities\BidirectionalDictionary.cs" />
|
||||
<Compile Include="Utilities\CollectionUtils.cs" />
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
<Compile Include="Serialization\JsonSerializerWriter.cs" />
|
||||
<Compile Include="Serialization\JsonTypeReflector.cs" />
|
||||
<Compile Include="Serialization\CachedAttributeGetter.cs" />
|
||||
<Compile Include="Serialization\ThreadSafeDictionaryWrapper.cs" />
|
||||
<Compile Include="TypeNameHandling.cs" />
|
||||
<Compile Include="Utilities\BidirectionalDictionary.cs" />
|
||||
<Compile Include="Utilities\ConvertUtils.cs" />
|
||||
|
||||
@@ -34,26 +34,11 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
internal static class CachedAttributeGetter<T> where T : Attribute
|
||||
{
|
||||
private static readonly Dictionary<ICustomAttributeProvider, T> TypeAttributeCache = new Dictionary<ICustomAttributeProvider, T>();
|
||||
private static readonly ThreadSafeDictionaryWrapper<ICustomAttributeProvider, T> TypeAttributeCache = new ThreadSafeDictionaryWrapper<ICustomAttributeProvider, T>(JsonTypeReflector.GetAttribute<T>);
|
||||
|
||||
public static T GetAttribute(ICustomAttributeProvider type)
|
||||
{
|
||||
T attribute;
|
||||
|
||||
if (TypeAttributeCache.TryGetValue(type, out attribute))
|
||||
return attribute;
|
||||
|
||||
// double check locking to avoid threading issues
|
||||
lock (TypeAttributeCache)
|
||||
{
|
||||
if (TypeAttributeCache.TryGetValue(type, out attribute))
|
||||
return attribute;
|
||||
|
||||
attribute = JsonTypeReflector.GetAttribute<T>(type);
|
||||
TypeAttributeCache[type] = attribute;
|
||||
|
||||
return attribute;
|
||||
}
|
||||
return TypeAttributeCache.Get(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
internal static readonly IMappingResolver Instance = new DefaultMappingResolver();
|
||||
|
||||
private readonly Dictionary<Type, JsonMemberMappingCollection> _typeMemberMappingsCache = new Dictionary<Type, JsonMemberMappingCollection>();
|
||||
private readonly ThreadSafeDictionaryWrapper<Type, JsonMemberMappingCollection> _typeMemberMappingsCache;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default members search flags.
|
||||
@@ -53,6 +53,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
public DefaultMappingResolver()
|
||||
{
|
||||
DefaultMembersSearchFlags = BindingFlags.Public | BindingFlags.Instance;
|
||||
|
||||
_typeMemberMappingsCache = new ThreadSafeDictionaryWrapper<Type, JsonMemberMappingCollection>(CreateMemberMappings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -63,22 +65,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// <returns>A collection of <see cref="JsonMemberMapping"/> to be used during serialization.</returns>
|
||||
public virtual JsonMemberMappingCollection ResolveMappings(Type type)
|
||||
{
|
||||
JsonMemberMappingCollection memberMappings;
|
||||
|
||||
if (_typeMemberMappingsCache.TryGetValue(type, out memberMappings))
|
||||
return memberMappings;
|
||||
|
||||
// double check locking to avoid threading issues
|
||||
lock (_typeMemberMappingsCache)
|
||||
{
|
||||
if (_typeMemberMappingsCache.TryGetValue(type, out memberMappings))
|
||||
return memberMappings;
|
||||
|
||||
memberMappings = CreateMemberMappings(type);
|
||||
_typeMemberMappingsCache[type] = memberMappings;
|
||||
|
||||
return memberMappings;
|
||||
}
|
||||
return _typeMemberMappingsCache.Get(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -64,10 +64,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (jsonWriter == null)
|
||||
throw new ArgumentNullException("jsonWriter");
|
||||
|
||||
if (value is JToken)
|
||||
((JToken)value).WriteTo(jsonWriter, (_serializer.Converters != null) ? _serializer.Converters.ToArray() : null);
|
||||
else
|
||||
SerializeValue(jsonWriter, value, null);
|
||||
SerializeValue(jsonWriter, value, null);
|
||||
}
|
||||
|
||||
private JsonSerializerProxy GetInternalSerializer()
|
||||
@@ -96,6 +93,10 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
writer.WriteValue(value);
|
||||
}
|
||||
else if (value is JToken)
|
||||
{
|
||||
((JToken)value).WriteTo(writer, (_serializer.Converters != null) ? _serializer.Converters.ToArray() : null);
|
||||
}
|
||||
else if (value is IList)
|
||||
{
|
||||
SerializeList(writer, (IList)value);
|
||||
@@ -224,7 +225,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (value is Guid || value is Type)
|
||||
if (value is Guid || value is Type || value is Uri)
|
||||
{
|
||||
writer.WriteValue(value.ToString());
|
||||
return;
|
||||
|
||||
@@ -43,8 +43,10 @@ namespace Newtonsoft.Json.Serialization
|
||||
public const string TypePropertyName = "$type";
|
||||
public const string ArrayValuesPropertyName = "$values";
|
||||
|
||||
private static readonly Dictionary<ICustomAttributeProvider, Type> ConverterTypeCache = new Dictionary<ICustomAttributeProvider, Type>();
|
||||
private static readonly Dictionary<Type, Type> AssociatedMetadataTypesCache = new Dictionary<Type, Type>();
|
||||
private static readonly ThreadSafeDictionaryWrapper<ICustomAttributeProvider, Type> ConverterTypeCache = new ThreadSafeDictionaryWrapper<ICustomAttributeProvider, Type>(GetConverterTypeFromAttribute);
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
private static readonly ThreadSafeDictionaryWrapper<Type, Type> AssociatedMetadataTypesCache = new ThreadSafeDictionaryWrapper<Type, Type>(GetAssociateMetadataTypeFromAttribute);
|
||||
#endif
|
||||
|
||||
public static JsonContainerAttribute GetJsonContainerAttribute(Type type)
|
||||
{
|
||||
@@ -79,26 +81,15 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
private static Type GetConverterType(ICustomAttributeProvider attributeProvider)
|
||||
{
|
||||
Type converterType;
|
||||
return ConverterTypeCache.Get(attributeProvider);
|
||||
}
|
||||
|
||||
if (ConverterTypeCache.TryGetValue(attributeProvider, out converterType))
|
||||
return converterType;
|
||||
|
||||
// double check locking to avoid threading issues
|
||||
lock (ConverterTypeCache)
|
||||
{
|
||||
if (ConverterTypeCache.TryGetValue(attributeProvider, out converterType))
|
||||
return converterType;
|
||||
|
||||
JsonConverterAttribute converterAttribute = GetAttribute<JsonConverterAttribute>(attributeProvider);
|
||||
converterType = (converterAttribute != null)
|
||||
? converterAttribute.ConverterType
|
||||
: null;
|
||||
|
||||
ConverterTypeCache[attributeProvider] = converterType;
|
||||
|
||||
return converterType;
|
||||
}
|
||||
private static Type GetConverterTypeFromAttribute(ICustomAttributeProvider attributeProvider)
|
||||
{
|
||||
JsonConverterAttribute converterAttribute = GetAttribute<JsonConverterAttribute>(attributeProvider);
|
||||
return (converterAttribute != null)
|
||||
? converterAttribute.ConverterType
|
||||
: null;
|
||||
}
|
||||
|
||||
public static JsonConverter GetConverter(ICustomAttributeProvider attributeProvider, Type targetConvertedType)
|
||||
@@ -121,25 +112,14 @@ namespace Newtonsoft.Json.Serialization
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
private static Type GetAssociatedMetadataType(Type type)
|
||||
{
|
||||
Type associatedMetadataType;
|
||||
return AssociatedMetadataTypesCache.Get(type);
|
||||
}
|
||||
|
||||
if (AssociatedMetadataTypesCache.TryGetValue(type, out associatedMetadataType))
|
||||
return associatedMetadataType;
|
||||
private static Type GetAssociateMetadataTypeFromAttribute(Type type)
|
||||
{
|
||||
MetadataTypeAttribute metadataTypeAttribute = ReflectionUtils.GetAttribute<MetadataTypeAttribute>(type, true);
|
||||
|
||||
// double check locking to avoid threading issues
|
||||
lock (AssociatedMetadataTypesCache)
|
||||
{
|
||||
if (AssociatedMetadataTypesCache.TryGetValue(type, out associatedMetadataType))
|
||||
return associatedMetadataType;
|
||||
|
||||
MetadataTypeAttribute metadataTypeAttribute = ReflectionUtils.GetAttribute<MetadataTypeAttribute>(type, true);
|
||||
if (metadataTypeAttribute != null)
|
||||
associatedMetadataType = metadataTypeAttribute.MetadataClassType;
|
||||
|
||||
AssociatedMetadataTypesCache[type] = associatedMetadataType;
|
||||
|
||||
return associatedMetadataType;
|
||||
}
|
||||
return (metadataTypeAttribute != null) ? metadataTypeAttribute.MetadataClassType : null;
|
||||
}
|
||||
|
||||
private static T GetAttribute<T>(Type type) where T : Attribute
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
|
||||
namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
internal class ThreadSafeDictionaryWrapper<TKey, TValue>
|
||||
{
|
||||
private Dictionary<TKey, TValue> _dictionary;
|
||||
private readonly Func<TKey, TValue> _creator;
|
||||
|
||||
public ThreadSafeDictionaryWrapper(Func<TKey, TValue> creator)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(creator, "creator");
|
||||
|
||||
_creator = creator;
|
||||
}
|
||||
|
||||
private TValue AddValue(TKey key)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
TValue value;
|
||||
|
||||
if (_dictionary == null)
|
||||
{
|
||||
_dictionary = new Dictionary<TKey, TValue>();
|
||||
value = _creator(key);
|
||||
_dictionary[key] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// double check locking
|
||||
if (_dictionary.TryGetValue(key, out value))
|
||||
return value;
|
||||
|
||||
Dictionary<TKey, TValue> newDictionary = new Dictionary<TKey, TValue>(_dictionary);
|
||||
value = _creator(key);
|
||||
newDictionary[key] = value;
|
||||
|
||||
_dictionary = newDictionary;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public TValue Get(TKey key)
|
||||
{
|
||||
if (_dictionary == null)
|
||||
return AddValue(key);
|
||||
|
||||
TValue value;
|
||||
if (!_dictionary.TryGetValue(key, out value))
|
||||
return AddValue(key);
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,8 +164,13 @@ namespace Newtonsoft.Json.Utilities
|
||||
if (initialValue is DateTime && targetType == typeof(DateTimeOffset))
|
||||
return new DateTimeOffset((DateTime)initialValue);
|
||||
|
||||
if (initialValue is string && targetType == typeof(Guid))
|
||||
return new Guid((string)initialValue);
|
||||
if (initialValue is string)
|
||||
{
|
||||
if (targetType == typeof(Guid))
|
||||
return new Guid((string)initialValue);
|
||||
if (targetType == typeof(Uri))
|
||||
return new Uri((string) initialValue);
|
||||
}
|
||||
|
||||
#if !PocketPC
|
||||
// see if source or target types have a TypeConverter that converts between the two
|
||||
|
||||
Reference in New Issue
Block a user