diff --git a/Src/Doc/ConvertingJSONandXML.html b/Src/Doc/ConvertingJSONandXML.html new file mode 100644 index 00000000..711d9778 --- /dev/null +++ b/Src/Doc/ConvertingJSONandXML.html @@ -0,0 +1,146 @@ + + + + Converting between JSON and XML + + + + + + +
+ Json.NET - Quick Starts & API Documentation
+ Converting between JSON and XML
+ +
+ +

Json.NET supports converting JSON to XML and vice versa using the + XmlNodeConverter.

+ +

+ Elements, attributes, text, comments, character data, processing instructions, + namespaces and the XML declaration are all preserved when converting between the + two. The only caveat is that it is possible to lose the order of differently + named nodes at the same level when they are grouped together into an array.

+

Conversion Rules

+ + +

SerializeXmlNode

+

The JsonConvert has two helper methods for converting between JSON and XML. The first is SerializeXmlNode. This method takes an +XmlNode and serializes it to JSON text.

+
+
+
+
string xml = @"<?xml version=""1.0"" standalone=""no""?>
+
<root>
+
  <person id=""1"">
+
  <name>Alan</name>
+
  <url>http://www.google.com</url>
+
  </person>
+
  <person id=""2"">
+
  <name>Louis</name>
+
  <url>http://www.yahoo.com</url>
+
  </person>
+
</root>";
+
 
+
XmlDocument doc = new XmlDocument();
+
doc.LoadXml(xml);
+
 
+
string jsonText = JsonConvert.SerializeXmlNode(doc);
+
//{
+
//  "?xml": {
+
//    "@version": "1.0",
+
//    "@standalone": "no"
+
//  },
+
//  "root": {
+
//    "person": [
+
//      {
+
//        "@id": "1",
+
//        "name": "Alan",
+
//        "url": "http://www.google.com"
+
//      },
+
//      {
+
//        "@id": "2",
+
//        "name": "Louis",
+
//        "url": "http://www.yahoo.com"
+
//      }
+
//    ]
+
//  }
+
//}
+
+ +
+
+ +

DeserializeXmlNode

+ +

The second helper method on JsonConvert is DeserializeXmlNode. This method takes + JSON text and deserializes it into a XmlNode.

+

Because valid XML must have one root element the JSON passed to + DeserializeXmlNode should have one property in the root JSON object. If the root + JSON object has multiple properties then the overload that also takes an element + name should be used. A root element with that name will be inserted into the + deserialized XmlNode.

+ +
+ +
+ +
+
string json = @"{
+
  ""?xml"": {
+
    ""@version"": ""1.0"",
+
    ""@standalone"": ""no""
+
  },
+
  ""root"": {
+
    ""person"": [
+
      {
+
        ""@id"": ""1"",
+
        ""name"": ""Alan"",
+
        ""url"": ""http://www.google.com""
+
      },
+
      {
+
        ""@id"": ""2"",
+
        ""name"": ""Louis"",
+
        ""url"": ""http://www.yahoo.com""
+
      }
+
    ]
+
  }
+
}";
+
 
+
XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json);
+
// <?xml version="1.0" standalone="no"?>
+
// <root>
+
//   <person id="1">
+
//   <name>Alan</name>
+
//   <url>http://www.google.com</url>
+
//   </person>
+
//   <person id="2">
+
//   <name>Louis</name>
+
//   <url>http://www.yahoo.com</url>
+
//   </person>
+
// </root>
+
+ + +
+
+ + +
+ + + + \ No newline at end of file diff --git a/Src/Doc/SelectToken.html b/Src/Doc/SelectToken.html new file mode 100644 index 00000000..cb013613 --- /dev/null +++ b/Src/Doc/SelectToken.html @@ -0,0 +1,106 @@ + + + + Querying LINQ to JSON with SelectToken + + + + + + +
+ Json.NET - Quick Starts & API Documentation
+ Querying LINQ to JSON with SelectToken
+ +
+ +

SelectToken provides a method to query LINQ to JSON using a single string path to a + desired JToken. SelectToken makes dynamic queries much easier because the entire + query is defined in a string.

+ +

SelectToken

+

SelectToken is a method on JToken and takes a string path to a child token. + SelectToken returns the child token or a null reference if a token couldn't be + found at the path's location.

+

The + path is made up of property names and array indexes separated by periods. Array indexes + can use either square or round brackets. Both + of the following are valid paths and are equivilent to each other: Manufacturers[0].Name + and Manufacturers(0).Name.

+ +
+
+
+
JObject o = JObject.Parse(@"{
+
  ""Stores"": [
+
    ""Lambton Quay"",
+
    ""Willis Street""
+
  ],
+
  ""Manufacturers"": [
+
    {
+
      ""Name"": ""Acme Co"",
+
      ""Products"": [
+
        {
+
          ""Name"": ""Anvil"",
+
          ""Price"": 50
+
        }
+
      ]
+
    },
+
    {
+
      ""Name"": ""Contoso"",
+
      ""Products"": [
+
        {
+
          ""Name"": ""Elbow Grease"",
+
          ""Price"": 99.95
+
        },
+
        {
+
          ""Name"": ""Headlight Fluid"",
+
          ""Price"": 4
+
        }
+
      ]
+
    }
+
  ]
+
}");
+
 
+
string name = (string)o.SelectToken("Manufacturers[0].Name");
+
// Acme Co
+
 
+
decimal productPrice = (decimal)o.SelectToken("Manufacturers[0].Products[0].Price");
+
// 50
+
 
+
string productName = (string)o.SelectToken("Manufacturers[1].Products[0].Name");
+
// Elbow Grease
+
+
+
+ +

SelectToken with LINQ

+ +

SelectToken can be used in combination with standard LINQ methods.

+ +
+ +
+ +
+
IList<string> storeNames = o.SelectToken("Stores").Select(s => (string)s).ToList();
+
// Lambton Quay
+
// Willis Street
+
 
+
IList<string> firstProductNames = o["Manufacturers"].Select(m => (string)m.SelectToken("Products[1].Name")).ToList();
+
// null
+
// Headlight Fluid
+
 
+
decimal totalPrice = o["Manufacturers"].Sum(m => (decimal)m.SelectToken("Products[0].Price"));
+
// 149.95
+
+ +
+
+ + +
+ + + + \ No newline at end of file diff --git a/Src/Doc/SerializingJSONFragments.html b/Src/Doc/SerializingJSONFragments.html new file mode 100644 index 00000000..aa5c0c98 --- /dev/null +++ b/Src/Doc/SerializingJSONFragments.html @@ -0,0 +1,125 @@ + + + + Serializing Partial JSON Fragments + + + + + + +
+ Json.NET - Quick Starts & API Documentation
+ Serializing Partial JSON Fragments
+ +
+ +

Often when working with large JSON documents you're only interested in a small fragment of information. + This scenario can be annoying when you want to serialize that Json.NET into .NET + objects because you have to define .NET classes for the entire JSON result.

+

With Json.NET it is easy to get around this problem. Using LINQ to JSON you can + extract the pieces of JSON you want to serialize before passing them to the Json.NET serializer.

+ +
+
+ +
+
public class SearchResult
+
{
+
  public string Title { get; set; }
+
  public string Content { get; set; }
+
  public string Url { get; set; }
+
}
+
+ +
+
+ +
+
+ +
+
string googleSearchText = @"{
+
  ""responseData"": {
+
    ""results"": [
+
      {
+
        ""GsearchResultClass"": ""GwebSearch"",
+
        ""unescapedUrl"": ""http://en.wikipedia.org/wiki/Paris_Hilton"",
+
        ""url"": ""http://en.wikipedia.org/wiki/Paris_Hilton"",
+
        ""visibleUrl"": ""en.wikipedia.org"",
+
        ""cacheUrl"": ""http://www.google.com/search?q=cache:TwrPfhd22hYJ:en.wikipedia.org"",
+
        ""title"": ""<b>Paris Hilton</b> - Wikipedia, the free encyclopedia"",
+
        ""titleNoFormatting"": ""Paris Hilton - Wikipedia, the free encyclopedia"",
+
        ""content"": ""[1] In 2006, she released her debut album...""
+
      },
+
      {
+
        ""GsearchResultClass"": ""GwebSearch"",
+
        ""unescapedUrl"": ""http://www.imdb.com/name/nm0385296/"",
+
        ""url"": ""http://www.imdb.com/name/nm0385296/"",
+
        ""visibleUrl"": ""www.imdb.com"",
+
        ""cacheUrl"": ""http://www.google.com/search?q=cache:1i34KkqnsooJ:www.imdb.com"",
+
        ""title"": ""<b>Paris Hilton</b>"",
+
        ""titleNoFormatting"": ""Paris Hilton"",
+
        ""content"": ""Self: Zoolander. Socialite <b>Paris Hilton</b>...""
+
      }
+
    ],
+
    ""cursor"": {
+
      ""pages"": [
+
        {
+
          ""start"": ""0"",
+
          ""label"": 1
+
        },
+
        {
+
          ""start"": ""4"",
+
          ""label"": 2
+
        },
+
        {
+
          ""start"": ""8"",
+
          ""label"": 3
+
        },
+
        {
+
          ""start"": ""12"",
+
          ""label"": 4
+
        }
+
      ],
+
      ""estimatedResultCount"": ""59600000"",
+
      ""currentPageIndex"": 0,
+
      ""moreResultsUrl"": ""http://www.google.com/search?oe=utf8&ie=utf8...""
+
    }
+
  },
+
  ""responseDetails"": null,
+
  ""responseStatus"": 200
+
}";
+
 
+
JObject googleSearch = JObject.Parse(googleSearchText);
+
 
+
// get JSON result objects into a list
+
IList<JToken> results = googleSearch["responseData"]["results"].Children().ToList();
+
 
+
// serialize JSON results into .NET objects
+
IList<SearchResult> searchResults = new List<SearchResult>();
+
foreach (JToken result in results)
+
{
+
  SearchResult searchResult = JsonConvert.DeserializeObject<SearchResult>(result.ToString());
+
  searchResults.Add(searchResult);
+
}
+
 
+
// Title = <b>Paris Hilton</b> - Wikipedia, the free encyclopedia
+
// Content = [1] In 2006, she released her debut album...
+
// Url = http://en.wikipedia.org/wiki/Paris_Hilton
+
 
+
// Title = <b>Paris Hilton</b>
+
// Content = Self: Zoolander. Socialite <b>Paris Hilton</b>...
+
// Url = http://www.imdb.com/name/nm0385296/
+
+ + +
+
+ + +
+ + + + \ No newline at end of file diff --git a/Src/doc.shfbproj b/Src/Doc/doc.shfbproj similarity index 58% rename from Src/doc.shfbproj rename to Src/Doc/doc.shfbproj index f31230b3..5b9f6125 100644 --- a/Src/doc.shfbproj +++ b/Src/Doc/doc.shfbproj @@ -36,17 +36,20 @@ Prototype MemberName - - + + + - -The <b>Newtonsoft.Json</b> namespace provides classes that are used to implement the core services of the framework. -The <b>Newtonsoft.Json.Converters</b> namespace provides classes that inherit from <a href="T_Newtonsoft_Json_JsonConverter.htm">JsonConverter</a>. -The <b>Newtonsoft.Json.Linq</b> namespace provides classes that are used to implement LINQ to JSON. -The <b>Newtonsoft.Json.Linq.ComponentModel</b> namespace provides classes for LINQ to JSON databinding. -The <b>Newtonsoft.Json.Schema</b> namespace provides classes that are used to implement JSON schema. -The <b>Newtonsoft.Json.Linq</b> namespace provides classes that are used when serializing and deserializing JSON. - + + The <b>Newtonsoft.Json</b> namespace provides classes that are used to implement the core services of the framework. + The <b>Newtonsoft.Json.Converters</b> namespace provides classes that inherit from <a href="T_Newtonsoft_Json_JsonConverter.htm">JsonConverter</a>. + The <b>Newtonsoft.Json.Linq</b> namespace provides classes that are used to implement LINQ to JSON. + The <b>Newtonsoft.Json.Linq.ComponentModel</b> namespace provides classes for LINQ to JSON databinding. + The <b>Newtonsoft.Json.Schema</b> namespace provides classes that are used to implement JSON schema. + The <b>Newtonsoft.Json.Linq</b> namespace provides classes that are used when serializing and deserializing JSON. + + The <b>Newtonsoft.Json.Linq</b> namespace provides classes that are used to implement BSON. + @@ -61,6 +64,10 @@ + + + + diff --git a/Src/Doc/doc.sitemap b/Src/Doc/doc.sitemap index f2a752dd..027c96b4 100644 --- a/Src/Doc/doc.sitemap +++ b/Src/Doc/doc.sitemap @@ -11,7 +11,11 @@ + + + + - + \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs index a3dc965f..a446d61d 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs @@ -552,6 +552,124 @@ namespace Newtonsoft.Json.Tests.Converters Assert.AreEqual(@"Text", newDoc.InnerXml); } + [Test] + public void SerializeExample() + { + string xml = @" + + + Alan + http://www.google.com + + + Louis + http://www.yahoo.com + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + string jsonText = JsonConvert.SerializeXmlNode(doc); + // { + // "?xml": { + // "@version": "1.0", + // "@standalone": "no" + // }, + // "root": { + // "person": [ + // { + // "@id": "1", + // "name": "Alan", + // "url": "http://www.google.com" + // }, + // { + // "@id": "2", + // "name": "Louis", + // "url": "http://www.yahoo.com" + // } + // ] + // } + // } + + // format + jsonText = JObject.Parse(jsonText).ToString(); + + Assert.AreEqual(@"{ + ""?xml"": { + ""@version"": ""1.0"", + ""@standalone"": ""no"" + }, + ""root"": { + ""person"": [ + { + ""@id"": ""1"", + ""name"": ""Alan"", + ""url"": ""http://www.google.com"" + }, + { + ""@id"": ""2"", + ""name"": ""Louis"", + ""url"": ""http://www.yahoo.com"" + } + ] + } +}", jsonText); + + XmlDocument newDoc = (XmlDocument)JsonConvert.DeserializeXmlNode(jsonText); + + Assert.AreEqual(doc.InnerXml, newDoc.InnerXml); + } + + [Test] + public void DeserializeExample() + { + string json = @"{ + ""?xml"": { + ""@version"": ""1.0"", + ""@standalone"": ""no"" + }, + ""root"": { + ""person"": [ + { + ""@id"": ""1"", + ""name"": ""Alan"", + ""url"": ""http://www.google.com"" + }, + { + ""@id"": ""2"", + ""name"": ""Louis"", + ""url"": ""http://www.yahoo.com"" + } + ] + } + }"; + + XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json); + // + // + // + // Alan + // http://www.google.com + // + // + // Louis + // http://www.yahoo.com + // + // + + Assert.AreEqual(@" + + +Alan +http://www.google.com + + +Louis +http://www.yahoo.com + +".Replace(Environment.NewLine, string.Empty), doc.InnerXml); + } } } #endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs index 8ab36e32..be77c606 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs @@ -415,5 +415,19 @@ Parameter name: index")] Assert.AreEqual(3, (int)a[key]); } + + [Test] + public void ReplaceAll() + { + JArray a = new JArray(new [] { 1, 2, 3 }); + Assert.AreEqual(3, a.Count); + Assert.AreEqual(1, (int)a[0]); + Assert.AreEqual(2, (int)a[1]); + Assert.AreEqual(3, (int)a[2]); + + a.ReplaceAll(1); + Assert.AreEqual(1, a.Count); + Assert.AreEqual(1, (int)a[0]); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/JPathTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JPathTests.cs index 639c0af7..4ac9c06d 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JPathTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JPathTests.cs @@ -242,5 +242,72 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(JTokenType.Integer, t.Type); Assert.AreEqual(3, (int)t); } + + [Test] + public void Example() + { + JObject o = JObject.Parse(@"{ + ""Stores"": [ + ""Lambton Quay"", + ""Willis Street"" + ], + ""Manufacturers"": [ + { + ""Name"": ""Acme Co"", + ""Products"": [ + { + ""Name"": ""Anvil"", + ""Price"": 50 + } + ] + }, + { + ""Name"": ""Contoso"", + ""Products"": [ + { + ""Name"": ""Elbow Grease"", + ""Price"": 99.95 + }, + { + ""Name"": ""Headlight Fluid"", + ""Price"": 4 + } + ] + } + ] + }"); + + string name = (string)o.SelectToken("Manufacturers[0].Name"); + // Acme Co + + decimal productPrice = (decimal)o.SelectToken("Manufacturers[0].Products[0].Price"); + // 50 + + string productName = (string)o.SelectToken("Manufacturers[1].Products[0].Name"); + // Elbow Grease + + Assert.AreEqual("Acme Co", name); + Assert.AreEqual(50m, productPrice); + Assert.AreEqual("Elbow Grease", productName); + + IList storeNames = o.SelectToken("Stores").Select(s => (string)s).ToList(); + // Lambton Quay + // Willis Street + + IList firstProductNames = o["Manufacturers"].Select(m => (string)m.SelectToken("Products[1].Name")).ToList(); + // null + // Headlight Fluid + + decimal totalPrice = o["Manufacturers"].Sum(m => (decimal)m.SelectToken("Products[0].Price")); + // 149.95 + + Assert.AreEqual(2, storeNames.Count); + Assert.AreEqual("Lambton Quay", storeNames[0]); + Assert.AreEqual("Willis Street", storeNames[1]); + Assert.AreEqual(2, firstProductNames.Count); + Assert.AreEqual(null, firstProductNames[0]); + Assert.AreEqual("Headlight Fluid", firstProductNames[1]); + Assert.AreEqual(149.95m, totalPrice); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index fdd81b1e..c79140d9 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -1993,5 +1993,118 @@ keyword such as type of business."" Assert.AreEqual(1, newFoo.Bars[1].Id); Assert.AreEqual(2, newFoo.Bars[2].Id); } + + [Test] + public void SerializeGuidKeyedDictionary() + { + Dictionary dictionary = new Dictionary(); + dictionary.Add(new Guid("F60EAEE0-AE47-488E-B330-59527B742D77"), 1); + dictionary.Add(new Guid("C2594C02-EBA1-426A-AA87-8DD8871350B0"), 2); + + string json = JsonConvert.SerializeObject(dictionary, Formatting.Indented); + Assert.AreEqual(@"{ + ""f60eaee0-ae47-488e-b330-59527b742d77"": 1, + ""c2594c02-eba1-426a-aa87-8dd8871350b0"": 2 +}", json); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Could not create string property name from type 'Newtonsoft.Json.Tests.TestObjects.Person'.")] + public void SerializePersonKeyedDictionary() + { + Dictionary dictionary = new Dictionary(); + dictionary.Add(new Person { Name = "p1" }, 1); + dictionary.Add(new Person { Name = "p2" }, 2); + + JsonConvert.SerializeObject(dictionary, Formatting.Indented); + } + + public class SearchResult + { + public string Title { get; set; } + public string Content { get; set; } + public string Url { get; set; } + } + + [Test] + public void SerializeFragment() + { + string googleSearchText = @"{ + ""responseData"": { + ""results"": [ + { + ""GsearchResultClass"": ""GwebSearch"", + ""unescapedUrl"": ""http://en.wikipedia.org/wiki/Paris_Hilton"", + ""url"": ""http://en.wikipedia.org/wiki/Paris_Hilton"", + ""visibleUrl"": ""en.wikipedia.org"", + ""cacheUrl"": ""http://www.google.com/search?q=cache:TwrPfhd22hYJ:en.wikipedia.org"", + ""title"": ""Paris Hilton - Wikipedia, the free encyclopedia"", + ""titleNoFormatting"": ""Paris Hilton - Wikipedia, the free encyclopedia"", + ""content"": ""[1] In 2006, she released her debut album..."" + }, + { + ""GsearchResultClass"": ""GwebSearch"", + ""unescapedUrl"": ""http://www.imdb.com/name/nm0385296/"", + ""url"": ""http://www.imdb.com/name/nm0385296/"", + ""visibleUrl"": ""www.imdb.com"", + ""cacheUrl"": ""http://www.google.com/search?q=cache:1i34KkqnsooJ:www.imdb.com"", + ""title"": ""Paris Hilton"", + ""titleNoFormatting"": ""Paris Hilton"", + ""content"": ""Self: Zoolander. Socialite Paris Hilton..."" + } + ], + ""cursor"": { + ""pages"": [ + { + ""start"": ""0"", + ""label"": 1 + }, + { + ""start"": ""4"", + ""label"": 2 + }, + { + ""start"": ""8"", + ""label"": 3 + }, + { + ""start"": ""12"", + ""label"": 4 + } + ], + ""estimatedResultCount"": ""59600000"", + ""currentPageIndex"": 0, + ""moreResultsUrl"": ""http://www.google.com/search?oe=utf8&ie=utf8..."" + } + }, + ""responseDetails"": null, + ""responseStatus"": 200 + }"; + + JObject googleSearch = JObject.Parse(googleSearchText); + + // get JSON result objects into a list + IList results = googleSearch["responseData"]["results"].Children().ToList(); + + // serialize JSON results into .NET objects + IList searchResults = new List(); + foreach (JToken result in results) + { + SearchResult searchResult = JsonConvert.DeserializeObject(result.ToString()); + searchResults.Add(searchResult); + } + + // Title = Paris Hilton - Wikipedia, the free encyclopedia + // Content = [1] In 2006, she released her debut album... + // Url = http://en.wikipedia.org/wiki/Paris_Hilton + + // Title = Paris Hilton + // Content = Self: Zoolander. Socialite Paris Hilton... + // Url = http://www.imdb.com/name/nm0385296/ + + Assert.AreEqual(2, searchResults.Count); + Assert.AreEqual("Paris Hilton - Wikipedia, the free encyclopedia", searchResults[0].Title); + Assert.AreEqual("Paris Hilton", searchResults[1].Title); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs b/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs index be102ab9..765909f4 100644 --- a/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs +++ b/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs @@ -25,8 +25,10 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; +using System.Threading; using NUnit.Framework; namespace Newtonsoft.Json.Tests @@ -34,6 +36,14 @@ namespace Newtonsoft.Json.Tests [TestFixture] public abstract class TestFixtureBase { + [TestFixtureSetUp] + protected void TestSetup() + { + //CultureInfo turkey = CultureInfo.CreateSpecificCulture("tr"); + //Thread.CurrentThread.CurrentCulture = turkey; + //Thread.CurrentThread.CurrentUICulture = turkey; + } + //public string GetOffset(DateTime value) //{ // TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(value.ToLocalTime()); diff --git a/Src/Newtonsoft.Json.sln b/Src/Newtonsoft.Json.sln index 17ca8b02..c02ca49d 100644 --- a/Src/Newtonsoft.Json.sln +++ b/Src/Newtonsoft.Json.sln @@ -17,7 +17,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doc", "Doc", "{8F9E13D9-418 Doc\custom.css = Doc\custom.css Doc\CustomCreationConverter.html = Doc\CustomCreationConverter.html Doc\DatesInJSON.html = Doc\DatesInJSON.html - doc.shfbproj = doc.shfbproj Doc\doc.sitemap = Doc\doc.sitemap Doc\donate.gif = Doc\donate.gif Doc\Introduction.html = Doc\Introduction.html @@ -25,10 +24,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doc", "Doc", "{8F9E13D9-418 Doc\PreserveObjectReferences.html = Doc\PreserveObjectReferences.html Doc\ReadingWritingJSON.html = Doc\ReadingWritingJSON.html Doc\ReducingSerializedJSONSize.html = Doc\ReducingSerializedJSONSize.html + Doc\SelectToken.html = Doc\SelectToken.html Doc\SerializationAttributes.html = Doc\SerializationAttributes.html Doc\SerializationErrorHandling.html = Doc\SerializationErrorHandling.html Doc\SerializingCollections.html = Doc\SerializingCollections.html Doc\SerializingJSON.html = Doc\SerializingJSON.html + Doc\SerializingJSONFragments.html = Doc\SerializingJSONFragments.html Doc\styles.css = Doc\styles.css EndProjectSection EndProject diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index e47d6517..825cfd87 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -441,7 +441,7 @@ namespace Newtonsoft.Json.Serialization foreach (DictionaryEntry entry in values) { - string propertyName = entry.Key.ToString(); + string propertyName = GetPropertyName(entry); try { @@ -477,6 +477,18 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnSerialized(values); } + private string GetPropertyName(DictionaryEntry entry) + { + string propertyName; + + if (entry.Key is IConvertible) + return Convert.ToString(entry.Key, CultureInfo.InvariantCulture); + else if (TryConvertToString(entry.Key, entry.Key.GetType(), out propertyName)) + return propertyName; + + throw new JsonSerializationException("Could not create string property name from type '{0}'.".FormatWith(CultureInfo.InvariantCulture, entry.Key.GetType())); + } + private void HandleError(JsonWriter writer, int initialDepth) { ClearErrorContext();