diff --git a/Doc/CreatingLINQtoJSON.aml b/Doc/CreatingLINQtoJSON.aml new file mode 100644 index 00000000..55fe758e --- /dev/null +++ b/Doc/CreatingLINQtoJSON.aml @@ -0,0 +1,50 @@ + + + + + As well as parsing JSON from existing JSON strings, LINQ to JSON objects can be created from scratch to create new JSON structures. + + +
+ Manually Creating JSON + + Setting values and creating objects and arrays one at a time gives you + total control but it is more verbose than other options. + + + +
+ +
+ Creating JSON with LINQ + + Declaratively creating JSON objects using LINQ is a fast way to create JSON from collections of values. + + + +
+ +
+ Creating JSON from an object + + The last option is to create a JSON object from a non-JSON type using the + Overload:Newtonsoft.Json.Linq.JObject.FromObject + method. Internally FromObject will use the JsonSerializer to serialize the object to LINQ to JSON objects instead of text. + + The example below is creating a JSON object from an anonymous object but any + .NET type can be used with FromObject to create JSON. + + + +
+ + + LINQ to JSON + LINQtoJSON.htm + _self + + + Overload:Newtonsoft.Json.Linq.JObject.FromObject + +
+
\ No newline at end of file diff --git a/Doc/JsonSchema.aml b/Doc/JsonSchema.aml new file mode 100644 index 00000000..feb06ea5 --- /dev/null +++ b/Doc/JsonSchema.aml @@ -0,0 +1,62 @@ + + + + + Json.NET supports the JSON Schema standard via the T:Newtonsoft.Json.Schema.JsonSchema + and T:Newtonsoft.Json.JsonValidatingReader classes. It sits under + the N:Newtonsoft.Json.Schema namespace. + JSON Schema is used to validate the structure and + data types of a piece of JSON, similar to XML Schema for XML. Read more about JSON Schema at + + json-schema.org + http://json-schema.org/ + _blank + + + +
+ Validating with JSON Schema + +The simplest way to check if JSON is valid is to load the JSON into a JObject or JArray and then +use the M:Newtonsoft.Json.Schema.Extensions.IsValid(Newtonsoft.Json.Linq.JToken,Newtonsoft.Json.Schema.JsonSchema) +method with the JSON Schema. + + + +To get validation error messages use the +M:Newtonsoft.Json.Schema.Extensions.IsValid(Newtonsoft.Json.Linq.JToken,Newtonsoft.Json.Schema.JsonSchema,System.Collections.Generic.IList{System.String}@) +or +M:Newtonsoft.Json.Schema.Extensions.Validate(Newtonsoft.Json.Linq.JToken,Newtonsoft.Json.Schema.JsonSchema,Newtonsoft.Json.Schema.ValidationEventHandler) +overloads. + + + +Internally IsValid uses T:Newtonsoft.Json.JsonValidatingReader +to perform the JSON Schema validation. To skip the overhead of loading JSON into a JObject/JArray, validating +the JSON and then deserializing the JSON into a class, JsonValidatingReader can be used with JsonSerializer to validate JSON while the object is being deserialized. + + + + +
+ +
+ Creating JSON Schemas + + +The simplest way to get a T:Newtonsoft.Json.Schema.JsonSchema object is to load it from a string or a file. + + +It is also possible to create JsonSchema objects in code. + + + +
+ + T:Newtonsoft.Json.Schema.JsonSchema + T:Newtonsoft.Json.JsonValidatingReader + + +
+
\ No newline at end of file diff --git a/Doc/LINQtoJSON.aml b/Doc/LINQtoJSON.aml index faba2f45..c4bca7b9 100644 --- a/Doc/LINQtoJSON.aml +++ b/Doc/LINQtoJSON.aml @@ -2,86 +2,58 @@ - LINQ to JSON is a programming API for working with JSON objects. - The API has been designed with LINQ in mind to enable to quick querying + LINQ to JSON is an API for working with JSON objects. + It has been designed with LINQ in mind to enable to quick querying and creation of JSON objects. LINQ to JSON sits under the N:Newtonsoft.Json.Linq namespace. + - -
- Reading JSON - - JSON values can be read from a string use the - M:Newtonsoft.Json.Linq.JToken.Parse(System.String) - method. - - - - -
-
- Creating JSON - - - There are a number of different options when it comes to creating - JSON using LINQ to JSON. - - The first option is to set values one at a time. You - have total control but it is more verbose than other options. - - - - Another option is to create JSON objects declaratively using LINQ. - - - - Finally you can create a JSON object from a non-JSON type using the - Overload:Newtonsoft.Json.Linq.JObject.FromObject - method. The example below is creating a JSON object from an anonymous object but any - .NET type can be used with FromObject to create JSON. - - - -
-
- Querying JSON - - - The properties and methods that are the most useful when querying JSON - objects are - M:Newtonsoft.Json.Linq.JToken.Children - and - P:Newtonsoft.Json.Linq.JToken.Item(System.Object). - - Children returns all the children of that object. If it is a - JObject it will return a collection of properties to work with and if - it is a JArray you will get a collection of the array's values. - - The index property is used to get a specific child, either by - index position for JSON arrays or property name for JSON objects. - - - - LINQ to JSON can also be used to manually convert from JSON to a .NET object. - - - - Manually serializing and deserializing between .NET objects is most useful when - working with JSON that doesn't closely match your .NET objects. - - - -
+
+ Topics + + Select a topic below for more information: + + + + + Parsing JSON + ParsingLINQtoJSON.htm + _self + + + + + + + Creating JSON + CreatingLINQtoJSON.htm + _self + + + + + + + Querying JSON with LINQ + QueryingLINQtoJSON.htm + _self + + + + + + + Querying JSON with SelectToken + SelectToken.htm + _self + + + + + +
- - Querying LINQ to JSON with SelectToken - SelectToken.htm - _self - - T:Newtonsoft.Json.Linq.JObject T:Newtonsoft.Json.Linq.JArray T:Newtonsoft.Json.Linq.JValue diff --git a/Doc/ParsingLINQtoJSON.aml b/Doc/ParsingLINQtoJSON.aml new file mode 100644 index 00000000..8a2efc11 --- /dev/null +++ b/Doc/ParsingLINQtoJSON.aml @@ -0,0 +1,37 @@ + + + + + LINQ to JSON has methods available for parsing JSON from a string or loading JSON directly from a file. + + +
+ Parsing JSON text + + JSON values can be read from a string using + M:Newtonsoft.Json.Linq.JToken.Parse(System.String). + + + + +
+ +
+ Loading JSON from a file + + JSON can also be loaded directly from a file using M:Newtonsoft.Json.Linq.JToken.ReadFrom(Newtonsoft.Json.JsonReader). + + +
+ + + LINQ to JSON + LINQtoJSON.htm + _self + + + M:Newtonsoft.Json.Linq.JToken.Parse(System.String) + M:Newtonsoft.Json.Linq.JToken.ReadFrom(Newtonsoft.Json.JsonReader) + +
+
\ No newline at end of file diff --git a/Doc/QueryingLINQtoJSON.aml b/Doc/QueryingLINQtoJSON.aml new file mode 100644 index 00000000..bf2f8710 --- /dev/null +++ b/Doc/QueryingLINQtoJSON.aml @@ -0,0 +1,60 @@ + + + + + LINQ to JSON provides a number of methods for getting data from its objects. The index methods on JObject/JArray let you quickly get data by its property name + on an object or index in a collection, while M:Newtonsoft.Json.Linq.JToken.Children lets you get ranges + of data as IEnumerable<JToken> to then query using LINQ. + + +
+ Getting values by Property Name or Collection Index + + + The simplest way to get a value from LINQ to JSON is to use the + P:Newtonsoft.Json.Linq.JToken.Item(System.Object) index on + JObject/JArray and then cast the returned T:Newtonsoft.Json.Linq.JValue to the type you want. + + + + + +
+
+ Querying with LINQ + + JObject/JArray can also be queried using LINQ. M:Newtonsoft.Json.Linq.JToken.Children + returns the children values of a JObject/JArray + as an IEnumerable<JToken> that can then be queried with the standard Where/OrderBy/Select LINQ operators. + + + M:Newtonsoft.Json.Linq.JToken.Children returns all the children of a token. If it is a + JObject it will return a collection of properties to work with and if + it is a JArray you will get a collection of the array's values. + + + + + LINQ to JSON can also be used to manually convert JSON to a .NET object. + + + + Manually serializing and deserializing between .NET objects is useful when you are + working with JSON that doesn't closely match your .NET objects. + + + +
+ + + LINQ to JSON + LINQtoJSON.htm + _self + + + P:Newtonsoft.Json.Linq.JToken.Item(System.Object) + M:Newtonsoft.Json.Linq.JToken.Children + +
+
\ No newline at end of file diff --git a/Doc/doc.content b/Doc/doc.content index ce0c7870..a7d32cd5 100644 --- a/Doc/doc.content +++ b/Doc/doc.content @@ -1,7 +1,7 @@  - + @@ -15,9 +15,13 @@ - - + + + + + - + + \ No newline at end of file diff --git a/Doc/doc.shfbproj b/Doc/doc.shfbproj index 4a9ea64c..9be93ec3 100644 --- a/Doc/doc.shfbproj +++ b/Doc/doc.shfbproj @@ -140,6 +140,12 @@ + + + + + + diff --git a/Src/Newtonsoft.Json.Tests/Documentation/JsonSchemaTests.cs b/Src/Newtonsoft.Json.Tests/Documentation/JsonSchemaTests.cs new file mode 100644 index 00000000..09baeb2d --- /dev/null +++ b/Src/Newtonsoft.Json.Tests/Documentation/JsonSchemaTests.cs @@ -0,0 +1,184 @@ +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + +#if !(NET35 || NET20 || PORTABLE) +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Dynamic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +#if !NETFX_CORE +using NUnit.Framework; +#else +using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; +using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; +using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; +#endif +using Newtonsoft.Json.Schema; +using Newtonsoft.Json.Serialization; +using Newtonsoft.Json.Tests.TestObjects; +using Newtonsoft.Json.Utilities; +using System.Globalization; +using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs; +using File = System.IO.File; + +namespace Newtonsoft.Json.Tests.Documentation +{ + public class JsonSchemaTests + { + public void IsValidBasic() + { + #region IsValidBasic + string schemaJson = @"{ + 'description': 'A person', + 'type': 'object', + 'properties': + { + 'name': {'type':'string'}, + 'hobbies': { + 'type': 'array', + 'items': {'type':'string'} + } + } + }"; + + JsonSchema schema = JsonSchema.Parse(schemaJson); + + JObject person = JObject.Parse(@"{ + 'name': 'James', + 'hobbies': ['.NET', 'Blogging', 'Reading', 'Xbox', 'LOLCATS'] + }"); + + bool valid = person.IsValid(schema); + // true + #endregion + } + + public void IsValidMessages() + { + string schemaJson = @"{ + 'description': 'A person', + 'type': 'object', + 'properties': + { + 'name': {'type':'string'}, + 'hobbies': { + 'type': 'array', + 'items': {'type':'string'} + } + } + }"; + + #region IsValidMessages + JsonSchema schema = JsonSchema.Parse(schemaJson); + + JObject person = JObject.Parse(@"{ + 'name': null, + 'hobbies': ['Invalid content', 0.123456789] + }"); + + IList messages; + bool valid = person.IsValid(schema, out messages); + // false + // Invalid type. Expected String but got Null. Line 2, position 21. + // Invalid type. Expected String but got Float. Line 3, position 51. + #endregion + } + + public void JsonValidatingReader() + { + string schemaJson = "{}"; + + #region JsonValidatingReader + string json = @"{ + 'name': 'James', + 'hobbies': ['.NET', 'Blogging', 'Reading', 'Xbox', 'LOLCATS'] + }"; + + JsonTextReader reader = new JsonTextReader(new StringReader(json)); + + JsonValidatingReader validatingReader = new JsonValidatingReader(reader); + validatingReader.Schema = JsonSchema.Parse(schemaJson); + + IList messages = new List(); + validatingReader.ValidationEventHandler += (o, a) => messages.Add(a.Message); + + JsonSerializer serializer = new JsonSerializer(); + Person p = serializer.Deserialize(validatingReader); + #endregion + } + + public void LoadJsonSchema() + { + #region LoadJsonSchema + // load from a string + JsonSchema schema1 = JsonSchema.Parse(@"{'type':'object'}"); + + // load from a file + using (TextReader reader = File.OpenText(@"c:\schema\Person.json")) + { + JsonSchema schema2 = JsonSchema.Read(new JsonTextReader(reader)); + + // do stuff + } + #endregion + } + + public void ManuallyCreateJsonSchema() + { + #region ManuallyCreateJsonSchema + JsonSchema schema = new JsonSchema(); + schema.Type = JsonSchemaType.Object; + schema.Properties = new Dictionary + { + {"name", new JsonSchema {Type = JsonSchemaType.String}}, + { + "hobbies", new JsonSchema + { + Type = JsonSchemaType.Array, + Items = new List { new JsonSchema {Type = JsonSchemaType.String} } + } + }, + }; + + JObject person = JObject.Parse(@"{ + 'name': 'James', + 'hobbies': ['.NET', 'Blogging', 'Reading', 'Xbox', 'LOLCATS'] + }"); + + bool valid = person.IsValid(schema); + // true + #endregion + + Assert.IsTrue(valid); + } + } +} +#endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Documentation/LinqToJsonTests.cs b/Src/Newtonsoft.Json.Tests/Documentation/LinqToJsonTests.cs index 75bb7b6d..4ae7b133 100644 --- a/Src/Newtonsoft.Json.Tests/Documentation/LinqToJsonTests.cs +++ b/Src/Newtonsoft.Json.Tests/Documentation/LinqToJsonTests.cs @@ -46,11 +46,43 @@ using Newtonsoft.Json.Tests.TestObjects; using Newtonsoft.Json.Utilities; using System.Globalization; using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs; +using File = System.IO.File; namespace Newtonsoft.Json.Tests.Documentation { + public static class File + { + public static StreamReader OpenText(string path) + { + return null; + } + } + public class LinqToJsonTests { + public void LinqToJsonBasic() + { + #region LinqToJsonBasic + JObject o = JObject.Parse(@"{ + 'CPU': 'Intel', + 'Drives': [ + 'DVD read/writer', + '500 gigabyte hard drive' + ] + }"); + + string cpu = (string)o["CPU"]; + // Intel + + string firstDrive = (string)o["Drives"][0]; + // DVD read/writer + + IList allDrives = o["Drives"].Select(t => (string)t).ToList(); + // DVD read/writer + // 500 gigabyte hard drive + #endregion + } + public void LinqToJsonCreateNormal() { #region LinqToJsonCreateNormal @@ -194,6 +226,65 @@ namespace Newtonsoft.Json.Tests.Documentation #endregion } + public void LinqToJsonReadObject() + { + #region LinqToJsonReadObject + using (StreamReader reader = File.OpenText(@"c:\person.json")) + { + JObject o = (JObject)JToken.ReadFrom(new JsonTextReader(reader)); + // do stuff + } + #endregion + } + + public void LinqToJsonSimpleQuerying() + { + #region LinqToJsonSimpleQuerying + string json = @"{ + 'channel': { + 'title': 'James Newton-King', + 'link': 'http://james.newtonking.com', + 'description': 'James Newton-King's blog.', + 'item': [ + { + 'title': 'Json.NET 1.3 + New license + Now on CodePlex', + 'description': 'Annoucing the release of Json.NET 1.3, the MIT license and the source being available on CodePlex', + 'link': 'http://james.newtonking.com/projects/json-net.aspx', + 'categories': [ + 'Json.NET', + 'CodePlex' + ] + }, + { + 'title': 'LINQ to JSON beta', + 'description': 'Annoucing LINQ to JSON', + 'link': 'http://james.newtonking.com/projects/json-net.aspx', + 'categories': [ + 'Json.NET', + 'LINQ' + ] + } + ] + } + }"; + + JObject rss = JObject.Parse(json); + + string rssTitle = (string)rss["channel"]["title"]; + // James Newton-King + + string itemTitle = (string)rss["channel"]["item"][0]["title"]; + // Json.NET 1.3 + New license + Now on CodePlex + + JArray categories = (JArray)rss["channel"]["item"][0]["categories"]; + // ["Json.NET", "CodePlex"] + + IList categoriesText = categories.Select(c => (string)c).ToList(); + // Json.NET + // CodePlex + #endregion + } + public void LinqToJsonQuerying() { JObject rss = new JObject(); diff --git a/Src/Newtonsoft.Json.Tests/Documentation/SerializationTests.cs b/Src/Newtonsoft.Json.Tests/Documentation/SerializationTests.cs index 2964b6e7..2b82d61f 100644 --- a/Src/Newtonsoft.Json.Tests/Documentation/SerializationTests.cs +++ b/Src/Newtonsoft.Json.Tests/Documentation/SerializationTests.cs @@ -882,6 +882,30 @@ namespace Newtonsoft.Json.Tests.Documentation // Url = http://www.imdb.com/name/nm0385296/ #endregion } + + public void SerializeMultidimensionalArrayExample() + { + string[,] famousCouples = new string[,] + { + {"Adam", "Eve"}, + {"Bonnie", "Clyde"}, + {"Donald", "Daisy"}, + {"Han", "Leia"} + }; + + string json = JsonConvert.SerializeObject(famousCouples, Formatting.Indented); + // [ + // ["Adam", "Eve"], + // ["Bonnie", "Clyde"], + // ["Donald", "Daisy"], + // ["Han", "Leia"] + // ] + + string[,] deserialized = JsonConvert.DeserializeObject(json); + + Console.WriteLine(deserialized[3, 0] + ", " + deserialized[3, 1]); + // Han, Leia + } } } #endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj index 90f04df7..6885929d 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj @@ -117,6 +117,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs index d692480f..9db01802 100644 --- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs +++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs @@ -768,6 +768,27 @@ namespace Newtonsoft.Json.Tests BenchmarkSerializeMethod(SerializeMethod.JsonNet, s); } + [Test] + public void ParseJObject() + { + Stopwatch timer = new Stopwatch(); + timer.Start(); + for (int i = 0; i < 100000; i++) + { + JObject o = JObject.Parse(@"{ + ""CPU"": ""Intel"", + ""Drives"": [ + ""DVD read/writer"", + ""500 gigabyte hard drive"" + ] +}"); + } + timer.Stop(); + + string linq = timer.Elapsed.TotalSeconds.ToString(); + Console.WriteLine(linq); + } + [Test] public void JObjectToString() { @@ -778,7 +799,7 @@ namespace Newtonsoft.Json.Tests for (int i = 0; i < Iterations; i++) { test["dummy"] = new JValue(i); - Encoding.UTF8.GetBytes(test.ToString(Formatting.None)); + test.ToString(Formatting.None); } return null; }, "JObject.ToString");