diff --git a/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs index 0a3ea691..802f4445 100644 --- a/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs @@ -44,6 +44,7 @@ using System.Runtime.Serialization.Json; #endif using Newtonsoft.Json.Tests.TestObjects; using System.Runtime.Serialization; +using System.Globalization; namespace Newtonsoft.Json.Tests { @@ -2048,20 +2049,20 @@ keyword such as type of business."" WriteEscapedJson(json); Assert.AreEqual(@"{ ""$id"": ""1"", - ""value"": [ + ""$values"": [ null, { ""$id"": ""2"", - ""value"": [ + ""$values"": [ null ] }, { ""$id"": ""3"", - ""value"": [ + ""$values"": [ { ""$id"": ""4"", - ""value"": [ + ""$values"": [ { ""$ref"": ""1"" } @@ -2078,20 +2079,20 @@ keyword such as type of business."" { string json = @"{ ""$id"": ""1"", - ""value"": [ + ""$values"": [ null, { ""$id"": ""2"", - ""value"": [ + ""$values"": [ null ] }, { ""$id"": ""3"", - ""value"": [ + ""$values"": [ { ""$id"": ""4"", - ""value"": [ + ""$values"": [ { ""$ref"": ""1"" } @@ -2119,20 +2120,20 @@ keyword such as type of business."" { string json = @"{ ""$id"": ""1"", - ""value"": [ + ""$values"": [ null, { ""$id"": ""2"", - ""value"": [ + ""$values"": [ null ] }, { ""$id"": ""3"", - ""value"": [ + ""$values"": [ { ""$id"": ""4"", - ""value"": [ + ""$values"": [ { ""$ref"": ""1"" } @@ -2245,7 +2246,7 @@ keyword such as type of business."" { CircularReferenceClass circularReferenceClass = (CircularReferenceClass) value; - string reference = serializer.ReferenceResolver.ResolveReference(circularReferenceClass); + string reference = serializer.ReferenceResolver.GetReference(circularReferenceClass); JObject me = new JObject(); me["$id"] = new JValue(reference); @@ -2271,7 +2272,7 @@ keyword such as type of business."" else { string reference = (string)o["$ref"]; - return serializer.ReferenceResolver.ResolveObject(reference); + return serializer.ReferenceResolver.ResolveReference(reference); } } @@ -2351,5 +2352,202 @@ keyword such as type of business."" Assert.AreEqual("c3", c1.Child.Child.Name); Assert.AreEqual("c1", c1.Child.Child.Child.Name); } + + [Test] + public void WriteTypeNameForObjects() + { + string employeeRef = typeof(Employee).AssemblyQualifiedName; + + Employee employee = new Employee(); + + string json = JsonConvert.SerializeObject(employee, Formatting.Indented, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects + }); + + Assert.AreEqual(@"{ + ""$id"": ""1"", + ""$type"": """ + employeeRef + @""", + ""Name"": null, + ""Manager"": null +}", json); + } + + [Test] + public void DeserializeTypeName() + { + string employeeRef = typeof(Employee).AssemblyQualifiedName; + + string json = @"{ + ""$id"": ""1"", + ""$type"": """ + employeeRef + @""", + ""Name"": ""Name!"", + ""Manager"": null +}"; + + object employee = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects + }); + + Assert.IsInstanceOfType(typeof(Employee), employee); + Assert.AreEqual("Name!", ((Employee)employee).Name); + } + + [Test] + public void SerializeGenericObjectListWithTypeName() + { + string employeeRef = typeof(Employee).AssemblyQualifiedName; + string personRef = typeof(Person).AssemblyQualifiedName; + + List values = new List + { + new Employee + { + Name = "Bob", + Manager = new Employee {Name = "Frank"} + }, + new Person + { + Department = "Department", + BirthDate = new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc), + LastModified = new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc) + }, + "String!", + int.MinValue + }; + + string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects + }); + + Assert.AreEqual(@"[ + { + ""$id"": ""1"", + ""$type"": """ + employeeRef + @""", + ""Name"": ""Bob"", + ""Manager"": { + ""$id"": ""2"", + ""$type"": """ + employeeRef + @""", + ""Name"": ""Frank"", + ""Manager"": null + } + }, + { + ""$type"": """ + personRef + @""", + ""Name"": null, + ""BirthDate"": ""\/Date(978134400000)\/"", + ""LastModified"": ""\/Date(978134400000)\/"" + }, + ""String!"", + -2147483648 +]", json); + } + + [Test] + public void DeserializeGenericObjectListWithTypeName() + { + string employeeRef = typeof (Employee).AssemblyQualifiedName; + string personRef = typeof (Person).AssemblyQualifiedName; + + string json = @"[ + { + ""$id"": ""1"", + ""$type"": """ + employeeRef + @""", + ""Name"": ""Bob"", + ""Manager"": { + ""$id"": ""2"", + ""$type"": """ + employeeRef + @""", + ""Name"": ""Frank"", + ""Manager"": null + } + }, + { + ""$type"": """ + personRef + @""", + ""Name"": null, + ""BirthDate"": ""\/Date(978134400000)\/"", + ""LastModified"": ""\/Date(978134400000)\/"" + }, + ""String!"", + -2147483648 +]"; + + List values = (List)JsonConvert.DeserializeObject(json, typeof(List), new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects + }); + + Assert.AreEqual(4, values.Count); + + Employee e = (Employee) values[0]; + Person p = (Person) values[1]; + + Assert.AreEqual("Bob", e.Name); + Assert.AreEqual("Frank", e.Manager.Name); + + Assert.AreEqual(null, p.Name); + Assert.AreEqual(new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc), p.BirthDate); + Assert.AreEqual(new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc), p.LastModified); + + Assert.AreEqual("String!", values[2]); + Assert.AreEqual(int.MinValue, values[3]); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException))] + public void DeserializeWithBadTypeName() + { + string employeeRef = typeof(Employee).AssemblyQualifiedName; + + string json = @"{ + ""$id"": ""1"", + ""$type"": """ + employeeRef + @""", + ""Name"": ""Name!"", + ""Manager"": null +}"; + + JsonConvert.DeserializeObject(json, typeof(Person), new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects + }); + } + + [Test] + public void DeserializeTypeNameWithNoTypeNameHandling() + { + string employeeRef = typeof(Employee).AssemblyQualifiedName; + + string json = @"{ + ""$id"": ""1"", + ""$type"": """ + employeeRef + @""", + ""Name"": ""Name!"", + ""Manager"": null +}"; + + JObject o = (JObject)JsonConvert.DeserializeObject(json); + + Assert.AreEqual(@"{ + ""Name"": ""Name!"", + ""Manager"": null +}", o.ToString()); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Type specified in JSON 'Newtonsoft.Json.Tests.TestObjects.Employee' was not resolved.")] + public void DeserializeTypeNameOnly() + { + string json = @"{ + ""$id"": ""1"", + ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Employee"", + ""Name"": ""Name!"", + ""Manager"": null +}"; + + JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects + }); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs index d82737a4..1b31b1e9 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs @@ -356,8 +356,6 @@ Parameter name: arrayIndex")] }"); // Invalid property identifier character: ]. Line 3, position 9. - - person = person; } [Test] diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index 5dfbc24e..1079115f 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -39,7 +39,7 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("3.0.0.0")] +[assembly: AssemblyVersion("3.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("3.0.0.0")] +[assembly: AssemblyFileVersion("3.5.0.0")] #endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs b/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs index ff2bcc12..e899b1a0 100644 --- a/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs +++ b/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs @@ -142,8 +142,6 @@ namespace Newtonsoft.Json.Tests.Schema bool valid = person.IsValid(schema); // true - - valid = valid; } } diff --git a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs index e0e91819..16a092fe 100644 --- a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs +++ b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -301,7 +301,7 @@ namespace Newtonsoft.Json.Tests.Schema JsonMemberMappingCollection mappings = base.ResolveMappings(type); JsonMemberMappingCollection c = new JsonMemberMappingCollection(); - CollectionUtils.AddRange(c, (IEnumerable)mappings.Where(m => m.MappingName != "Root")); + CollectionUtils.AddRange(c, (IEnumerable)mappings.Where(m => m.PropertyName != "Root")); return c; } diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/PrivateMembersClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/PrivateMembersClass.cs index 2b86d176..f71f7a9b 100644 --- a/Src/Newtonsoft.Json.Tests/TestObjects/PrivateMembersClass.cs +++ b/Src/Newtonsoft.Json.Tests/TestObjects/PrivateMembersClass.cs @@ -15,6 +15,7 @@ namespace Newtonsoft.Json.Tests.TestObjects public PrivateMembersClass() { + i = default(int); } private string _privateString; diff --git a/Src/Newtonsoft.Json/Converters/BinaryConverter.cs b/Src/Newtonsoft.Json/Converters/BinaryConverter.cs index ddc8402a..354b48f3 100644 --- a/Src/Newtonsoft.Json/Converters/BinaryConverter.cs +++ b/Src/Newtonsoft.Json/Converters/BinaryConverter.cs @@ -48,6 +48,7 @@ namespace Newtonsoft.Json.Converters /// /// The to write to. /// The value. + /// The calling serializer. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) @@ -82,6 +83,7 @@ namespace Newtonsoft.Json.Converters /// /// The to read from. /// Type of the object. + /// The calling serializer. /// The object value. public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer) { diff --git a/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs b/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs index 00a2dcdf..5d952038 100644 --- a/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs +++ b/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs @@ -30,16 +30,33 @@ using System.Text; namespace Newtonsoft.Json.Converters { + /// + /// Create a custom object + /// + /// public abstract class CustomCreationConverter : JsonConverter { + /// + /// Writes the JSON representation of the object. + /// + /// The to write to. + /// The value. + /// The calling serializer. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, value); } + /// + /// Reads the JSON representation of the object. + /// + /// The to read from. + /// Type of the object. + /// The calling serializer. + /// The object value. public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer) { - T value = Create(); + T value = Create(objectType); if (value == null) throw new JsonSerializationException("No object created."); @@ -47,8 +64,20 @@ namespace Newtonsoft.Json.Converters return value; } - public abstract T Create(); + /// + /// Creates an object which will then be populated by the serializer. + /// + /// Type of the object. + /// + public abstract T Create(Type objectType); + /// + /// Determines whether this instance can convert the specified object type. + /// + /// Type of the object. + /// + /// true if this instance can convert the specified object type; otherwise, false. + /// public override bool CanConvert(Type objectType) { return typeof (T).IsAssignableFrom(objectType); diff --git a/Src/Newtonsoft.Json/Converters/HtmlColorConverter.cs b/Src/Newtonsoft.Json/Converters/HtmlColorConverter.cs index de0e6dca..b4a29b7c 100644 --- a/Src/Newtonsoft.Json/Converters/HtmlColorConverter.cs +++ b/Src/Newtonsoft.Json/Converters/HtmlColorConverter.cs @@ -40,6 +40,7 @@ namespace Newtonsoft.Json.Converters /// Writes the JSON representation of the object. /// /// The to write to. + /// The calling serializer. /// The value. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { @@ -63,6 +64,7 @@ namespace Newtonsoft.Json.Converters /// /// The to read from. /// Type of the object. + /// The calling serializer. /// The object value. public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer) { diff --git a/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs b/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs index 91e869bc..74b40284 100644 --- a/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Globalization; using Newtonsoft.Json.Utilities; @@ -17,6 +14,7 @@ namespace Newtonsoft.Json.Converters /// /// The to write to. /// The value. + /// The calling serializer. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { long ticks; @@ -44,6 +42,7 @@ namespace Newtonsoft.Json.Converters /// /// The to read from. /// Type of the object. + /// The calling serializer. /// The object value. public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer) { diff --git a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs index e9fc1bf2..19b739c9 100644 --- a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs +++ b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs @@ -24,9 +24,6 @@ #endregion using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Globalization; using Newtonsoft.Json.Utilities; @@ -43,6 +40,7 @@ namespace Newtonsoft.Json.Converters /// /// The to write to. /// The value. + /// The calling serializer. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) @@ -65,6 +63,7 @@ namespace Newtonsoft.Json.Converters /// /// The to read from. /// Type of the object. + /// The calling serializer. /// The object value. public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer) { diff --git a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs index e840e008..ed2e06b6 100644 --- a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs @@ -46,6 +46,10 @@ namespace Newtonsoft.Json.Converters private const string DeclarationName = "?xml"; private const string JsonNamespaceUri = "http://james.newtonking.com/projects/json"; + /// + /// Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produces multiple root elements. + /// + /// The name of the deserialize root element. public string DeserializeRootElementName { get; set; } #region Writing @@ -53,6 +57,7 @@ namespace Newtonsoft.Json.Converters /// Writes the JSON representation of the object. /// /// The to write to. + /// The calling serializer. /// The value. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { @@ -260,6 +265,7 @@ namespace Newtonsoft.Json.Converters /// /// The to read from. /// Type of the object. + /// The calling serializer. /// The object value. public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer) { diff --git a/Src/Newtonsoft.Json/IJsonLineInfo.cs b/Src/Newtonsoft.Json/IJsonLineInfo.cs index 6c821adb..29c38f0e 100644 --- a/Src/Newtonsoft.Json/IJsonLineInfo.cs +++ b/Src/Newtonsoft.Json/IJsonLineInfo.cs @@ -5,11 +5,28 @@ using System.Text; namespace Newtonsoft.Json { + /// + /// Provides an interface to enable a class to return line and position information. + /// public interface IJsonLineInfo { + /// + /// Gets a value indicating whether the class can return line information. + /// + /// + /// true if LineNumber and LinePosition can be provided; otherwise, false. + /// bool HasLineInfo(); + /// + /// Gets the current line number. + /// + /// The current line number or 0 if no line information is available (for example, HasLineInfo returns false). int LineNumber { get; } + /// + /// Gets the current line position. + /// + /// The current line position or 0 if no line information is available (for example, HasLineInfo returns false). int LinePosition { get; } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonArrayAttribute.cs b/Src/Newtonsoft.Json/JsonArrayAttribute.cs index 4ea4b400..64a5d02a 100644 --- a/Src/Newtonsoft.Json/JsonArrayAttribute.cs +++ b/Src/Newtonsoft.Json/JsonArrayAttribute.cs @@ -31,13 +31,17 @@ using System.Text; namespace Newtonsoft.Json { /// - /// Instructs the how to serialize the object. + /// Instructs the how to serialize the collection. /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonArrayAttribute : JsonContainerAttribute { private bool _allowNullItems; + /// + /// Gets or sets a value indicating whether null items are allowed in the collection. + /// + /// true if null items are allowed in the collection; otherwise, false. public bool AllowNullItems { get { return _allowNullItems; } diff --git a/Src/Newtonsoft.Json/JsonContainerAttribute.cs b/Src/Newtonsoft.Json/JsonContainerAttribute.cs index bc223656..a83c8287 100644 --- a/Src/Newtonsoft.Json/JsonContainerAttribute.cs +++ b/Src/Newtonsoft.Json/JsonContainerAttribute.cs @@ -36,14 +36,32 @@ namespace Newtonsoft.Json [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public abstract class JsonContainerAttribute : Attribute { + /// + /// Gets or sets the id. + /// + /// The id. public string Id { get; set; } + /// + /// Gets or sets the title. + /// + /// The title. public string Title { get; set; } + /// + /// Gets or sets the description. + /// + /// The description. public string Description { get; set; } // yuck. can't set nullable properties on an attribute in C# // have to use this approach to get an unset default state internal bool? _isReference; + /// + /// Gets or sets a value that indicates whether to preserve object reference data. + /// + /// + /// true to keep object reference; otherwise, false. The default is false. + /// public bool IsReference { get { return _isReference ?? default(bool); } @@ -53,7 +71,7 @@ namespace Newtonsoft.Json /// /// Initializes a new instance of the class. /// - public JsonContainerAttribute() + protected JsonContainerAttribute() { } @@ -61,7 +79,7 @@ namespace Newtonsoft.Json /// Initializes a new instance of the class with the specified container Id. /// /// The container Id. - public JsonContainerAttribute(string id) + protected JsonContainerAttribute(string id) { Id = id; } diff --git a/Src/Newtonsoft.Json/JsonPropertyAttribute.cs b/Src/Newtonsoft.Json/JsonPropertyAttribute.cs index 0e801787..12ab217a 100644 --- a/Src/Newtonsoft.Json/JsonPropertyAttribute.cs +++ b/Src/Newtonsoft.Json/JsonPropertyAttribute.cs @@ -14,18 +14,30 @@ namespace Newtonsoft.Json internal DefaultValueHandling? _defaultValueHandling; internal ReferenceLoopHandling? _referenceLoopHandling; + /// + /// Gets or sets the null value handling used when serializing this property. + /// + /// The null value handling. public NullValueHandling NullValueHandling { get { return _nullValueHandling ?? default(NullValueHandling); } set { _nullValueHandling = value; } } + /// + /// Gets or sets the default value handling used when serializing this property. + /// + /// The default value handling. public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling ?? default(DefaultValueHandling); } set { _defaultValueHandling = value; } } + /// + /// Gets or sets the reference loop handling used when serializing this property. + /// + /// The reference loop handling. public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling ?? default(ReferenceLoopHandling); } @@ -38,6 +50,12 @@ namespace Newtonsoft.Json /// The name of the property. public string PropertyName { get; set; } + /// + /// Gets or sets a value indicating whether this property is required. + /// + /// + /// true if this property is required; otherwise, false. + /// public bool IsRequired { get; set; } /// diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs index 137486a5..86a38e2c 100644 --- a/Src/Newtonsoft.Json/JsonReader.cs +++ b/Src/Newtonsoft.Json/JsonReader.cs @@ -199,7 +199,7 @@ namespace Newtonsoft.Json } /// - /// Reads the next Json token from the stream. + /// Reads the next JSON token from the stream. /// /// true if the next token was read successfully; false if there are no more tokens to read. public abstract bool Read(); diff --git a/Src/Newtonsoft.Json/JsonReaderException.cs b/Src/Newtonsoft.Json/JsonReaderException.cs index 3d6efe44..78ac8912 100644 --- a/Src/Newtonsoft.Json/JsonReaderException.cs +++ b/Src/Newtonsoft.Json/JsonReaderException.cs @@ -24,8 +24,6 @@ #endregion using System; -using System.Collections.Generic; -using System.Text; namespace Newtonsoft.Json { @@ -34,7 +32,17 @@ namespace Newtonsoft.Json /// public class JsonReaderException : Exception { + /// + /// Gets the line number indicating where the error occurred. + /// + /// The line number indicating where the error occurred. public int LineNumber { get; private set; } + + + /// + /// Gets the line position indicating where the error occurred. + /// + /// The line position indicating where the error occurred. public int LinePosition { get; private set; } /// diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs index e929f0ef..91765a95 100644 --- a/Src/Newtonsoft.Json/JsonSerializer.cs +++ b/Src/Newtonsoft.Json/JsonSerializer.cs @@ -28,16 +28,18 @@ using System.Collections.Generic; using System.IO; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; +using System.Runtime.Serialization; namespace Newtonsoft.Json { /// - /// Serializes and deserializes objects into and from the Json format. - /// The enables you to control how objects are encoded into Json. + /// Serializes and deserializes objects into and from the JSON format. + /// The enables you to control how objects are encoded into JSON. /// public class JsonSerializer { #region Properties + private TypeNameHandling _typeNameHandling; private PreserveReferencesHandling _preserveReferencesHandling; private ReferenceLoopHandling _referenceLoopHandling; private MissingMemberHandling _missingMemberHandling; @@ -47,7 +49,11 @@ namespace Newtonsoft.Json private JsonConverterCollection _converters; private IMappingResolver _mappingResolver; private IReferenceResolver _referenceResolver; + private SerializationBinder _binder; + /// + /// Gets or sets the used by the serializer when resolving references. + /// public virtual IReferenceResolver ReferenceResolver { get @@ -66,6 +72,42 @@ namespace Newtonsoft.Json } } + /// + /// Gets or sets the used by the serializer when resolving type names. + /// + public virtual SerializationBinder Binder + { + get + { + return _binder; + } + set + { + if (value == null) + throw new ArgumentNullException("value", "Serialization binder cannot be null."); + + _binder = value; + } + } + + /// + /// Gets or sets how type name writing and reading is handled by the serializer. + /// + public virtual TypeNameHandling TypeNameHandling + { + get { return _typeNameHandling; } + set + { + if (value < TypeNameHandling.None || value > TypeNameHandling.All) + throw new ArgumentOutOfRangeException("value"); + + _typeNameHandling = value; + } + } + + /// + /// Gets or sets how object references are preserved by the serializer. + /// public virtual PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling; } @@ -169,6 +211,10 @@ namespace Newtonsoft.Json } } + /// + /// Gets or sets the mapping resolver used by the serializer when + /// mapping JSON properties to .NET objet members. + /// public virtual IMappingResolver MappingResolver { get { return _mappingResolver; } @@ -186,6 +232,9 @@ namespace Newtonsoft.Json _nullValueHandling = JsonSerializerSettings.DefaultNullValueHandling; _defaultValueHandling = JsonSerializerSettings.DefaultDefaultValueHandling; _objectCreationHandling = JsonSerializerSettings.DefaultObjectCreationHandling; + _preserveReferencesHandling = JsonSerializerSettings.DefaultPreserveReferencesHandling; + _typeNameHandling = JsonSerializerSettings.DefaultTypeNameHandling; + _binder = DefaultSerializationBinder.Instance; } /// @@ -202,23 +251,40 @@ namespace Newtonsoft.Json if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) jsonSerializer.Converters.AddRange(settings.Converters); + jsonSerializer.TypeNameHandling = settings.TypeNameHandling; jsonSerializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; jsonSerializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; jsonSerializer.MissingMemberHandling = settings.MissingMemberHandling; jsonSerializer.ObjectCreationHandling = settings.ObjectCreationHandling; jsonSerializer.NullValueHandling = settings.NullValueHandling; jsonSerializer.DefaultValueHandling = settings.DefaultValueHandling; - jsonSerializer.MappingResolver = settings.MappingResolver; + + if (settings.MappingResolver != null) + jsonSerializer.MappingResolver = settings.MappingResolver; + if (settings.ReferenceResolver != null) + jsonSerializer.ReferenceResolver = settings.ReferenceResolver; + if (settings.Binder != null) + jsonSerializer.Binder = settings.Binder; } return jsonSerializer; } + /// + /// Populates the JSON values onto the target object. + /// + /// The that contains the JSON structure to reader values from. + /// The target object to populate values onto. public void Populate(TextReader reader, object target) { Populate(new JsonTextReader(reader), target); } + /// + /// Populates the JSON values onto the target object. + /// + /// The that contains the JSON structure to reader values from. + /// The target object to populate values onto. public void Populate(JsonReader reader, object target) { PopulateInternal(reader, target); @@ -236,7 +302,7 @@ namespace Newtonsoft.Json /// /// Deserializes the Json structure contained by the specified . /// - /// The that contains the Json structure to deserialize. + /// The that contains the JSON structure to deserialize. /// The being deserialized. public object Deserialize(JsonReader reader) { diff --git a/Src/Newtonsoft.Json/JsonSerializerSettings.cs b/Src/Newtonsoft.Json/JsonSerializerSettings.cs index be76682b..674d1afb 100644 --- a/Src/Newtonsoft.Json/JsonSerializerSettings.cs +++ b/Src/Newtonsoft.Json/JsonSerializerSettings.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; +using System.Runtime.Serialization; namespace Newtonsoft.Json { @@ -18,6 +19,7 @@ namespace Newtonsoft.Json internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include; internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto; internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None; + internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None; /// /// Gets or sets how reference loops (e.g. a class referencing itself) is handled. @@ -49,8 +51,33 @@ namespace Newtonsoft.Json /// /// The converters. public IList Converters { get; set; } - public IMappingResolver MappingResolver { get; set; } + /// + /// Gets or sets how object references are preserved by the serializer. + /// + /// The preserve references handling. public PreserveReferencesHandling PreserveReferencesHandling { get; set; } + /// + /// Gets or sets how type name writing and reading is handled by the serializer. + /// + /// The type name handling. + public TypeNameHandling TypeNameHandling { get; set; } + + /// + /// Gets or sets the mapping resolver used by the serializer when + /// mapping JSON properties to .NET objet members. + /// + /// The mapping resolver. + public IMappingResolver MappingResolver { get; set; } + /// + /// Gets or sets the used by the serializer when resolving references. + /// + /// The reference resolver. + public IReferenceResolver ReferenceResolver { get; set; } + /// + /// Gets or sets the used by the serializer when resolving type names. + /// + /// The binder. + public SerializationBinder Binder { get; set; } /// /// Initializes a new instance of the class. @@ -63,6 +90,7 @@ namespace Newtonsoft.Json NullValueHandling = DefaultNullValueHandling; DefaultValueHandling = DefaultDefaultValueHandling; PreserveReferencesHandling = DefaultPreserveReferencesHandling; + TypeNameHandling = DefaultTypeNameHandling; Converters = new List(); } } diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs index 8786eb45..697cbad5 100644 --- a/Src/Newtonsoft.Json/JsonTextReader.cs +++ b/Src/Newtonsoft.Json/JsonTextReader.cs @@ -276,7 +276,7 @@ namespace Newtonsoft.Json } /// - /// Reads the next Json token from the stream. + /// Reads the next JSON token from the stream. /// /// /// true if the next token was read successfully; false if there are no more tokens to read. @@ -846,11 +846,23 @@ namespace Newtonsoft.Json _buffer.Clear(); } + /// + /// Gets a value indicating whether the class can return line information. + /// + /// + /// true if LineNumber and LinePosition can be provided; otherwise, false. + /// public bool HasLineInfo() { return true; } + /// + /// Gets the current line number. + /// + /// + /// The current line number or 0 if no line information is available (for example, HasLineInfo returns false). + /// public int LineNumber { get @@ -862,6 +874,12 @@ namespace Newtonsoft.Json } } + /// + /// Gets the current line position. + /// + /// + /// The current line position or 0 if no line information is available (for example, HasLineInfo returns false). + /// public int LinePosition { get { return _currentLinePosition; } diff --git a/Src/Newtonsoft.Json/JsonValidatingReader.cs b/Src/Newtonsoft.Json/JsonValidatingReader.cs index b9e57782..bcf0358a 100644 --- a/Src/Newtonsoft.Json/JsonValidatingReader.cs +++ b/Src/Newtonsoft.Json/JsonValidatingReader.cs @@ -35,6 +35,9 @@ using System.Text.RegularExpressions; namespace Newtonsoft.Json { + /// + /// Represents a reader that provides validation. + /// public class JsonValidatingReader : JsonReader, IJsonLineInfo { private class SchemaScope @@ -75,15 +78,6 @@ namespace Newtonsoft.Json private IEnumerable GetRequiredProperties(JsonSchemaModel schema) { return schema.Properties.Where(p => !p.Value.Optional).Select(p => p.Key); - //if (schema == null) - // return Enumerable.Empty(); - - //IEnumerable extendedRequiredProperties = GetRequiredProperties(schema.Extends); - - //if (_schema.Properties == null) - // return extendedRequiredProperties; - - //return extendedRequiredProperties.Union(schema.Properties.Where(p => !(p.Value.Optional ?? false)).Select(p => p.Key)); } } @@ -93,29 +87,52 @@ namespace Newtonsoft.Json private JsonSchemaModel _model; private SchemaScope _currentScope; + /// + /// Sets an event handler for receiving schema validation errors. + /// public event ValidationEventHandler ValidationEventHandler; + /// + /// Gets the text value of the current Json token. + /// + /// public override object Value { get { return _reader.Value; } } + /// + /// Gets the depth of the current token in the JSON document. + /// + /// The depth of the current token in the JSON document. public override int Depth { get { return _reader.Depth; } } + /// + /// Gets the quotation mark character used to enclose the value of a string. + /// + /// public override char QuoteChar { get { return _reader.QuoteChar; } protected internal set { } } + /// + /// Gets the type of the current Json token. + /// + /// public override JsonToken TokenType { get { return _reader.TokenType; } } + /// + /// Gets The Common Language Runtime (CLR) type for the current Json token. + /// + /// public override Type ValueType { get { return _reader.ValueType; } @@ -204,6 +221,11 @@ namespace Newtonsoft.Json throw exception; } + /// + /// Initializes a new instance of the class that + /// validates the content returned from the given . + /// + /// The to read from while validating. public JsonValidatingReader(JsonReader reader) { ValidationUtils.ArgumentNotNull(reader, "reader"); @@ -211,6 +233,10 @@ namespace Newtonsoft.Json _stack = new Stack(); } + /// + /// Gets or sets the schema. + /// + /// The schema. public JsonSchema Schema { get { return _schema; } @@ -224,6 +250,10 @@ namespace Newtonsoft.Json } } + /// + /// Gets the used to construct this . + /// + /// The specified in the constructor. public JsonReader Reader { get { return _reader; } @@ -274,6 +304,12 @@ namespace Newtonsoft.Json } } + /// + /// Reads the next JSON token from the stream. + /// + /// + /// true if the next token was read successfully; false if there are no more tokens to read. + /// public override bool Read() { if (!_reader.Read()) @@ -476,7 +512,7 @@ namespace Newtonsoft.Json ValidateInEnumAndNotDisallowed(schema); - double value = Convert.ToDouble(_reader.Value); + double value = Convert.ToDouble(_reader.Value, CultureInfo.InvariantCulture); if (schema.Maximum != null && value > schema.Maximum) RaiseError("Float {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Maximum), schema); diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index b03078d5..f934f824 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -298,15 +298,20 @@ namespace Newtonsoft.Json { ValidationUtils.ArgumentNotNull(reader, "reader"); - int currentDepth; + int initialDepth; if (reader.TokenType == JsonToken.None) - currentDepth = -1; + initialDepth = -1; else if (!IsStartToken(reader.TokenType)) - currentDepth = reader.Depth + 1; + initialDepth = reader.Depth + 1; else - currentDepth = reader.Depth; + initialDepth = reader.Depth; + WriteToken(reader, initialDepth); + } + + internal void WriteToken(JsonReader reader, int initialDepth) + { do { switch (reader.TokenType) @@ -373,7 +378,7 @@ namespace Newtonsoft.Json } while ( // stop if we have reached the end of the token being read - currentDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0) + initialDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0) && reader.Read()); } diff --git a/Src/Newtonsoft.Json/Linq/JArray.cs b/Src/Newtonsoft.Json/Linq/JArray.cs index 726550aa..3d1e666f 100644 --- a/Src/Newtonsoft.Json/Linq/JArray.cs +++ b/Src/Newtonsoft.Json/Linq/JArray.cs @@ -149,6 +149,12 @@ namespace Newtonsoft.Json.Linq return FromObject(o, new JsonSerializer()); } + /// + /// Creates a from an object. + /// + /// The object that will be used to create . + /// The that will be used to read the object. + /// A with the values of the specified object public static new JArray FromObject(object o, JsonSerializer jsonSerializer) { JToken token = FromObjectInternal(o, jsonSerializer); diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 2a4d5006..db0042d7 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -230,6 +230,12 @@ namespace Newtonsoft.Json.Linq return FromObject(o, new JsonSerializer()); } + /// + /// Creates a from an object. + /// + /// The object that will be used to create . + /// The that will be used to read the object. + /// A with the values of the specified object public static new JObject FromObject(object o, JsonSerializer jsonSerializer) { JToken token = FromObjectInternal(o, jsonSerializer); @@ -399,6 +405,12 @@ namespace Newtonsoft.Json.Linq return ContentsHashCode(); } + /// + /// Returns an enumerator that iterates through the collection. + /// + /// + /// A that can be used to iterate through the collection. + /// public IEnumerator> GetEnumerator() { foreach (JProperty property in Properties()) diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index 432d71cb..c5470d54 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -26,7 +26,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.IO; using Newtonsoft.Json.Utilities; using System.Diagnostics; @@ -164,6 +163,10 @@ namespace Newtonsoft.Json.Linq { } + /// + /// Adds the specified content immediately after this token. + /// + /// A content object that contains simple content or a collection of content objects to be added after this token. public void AddAfterSelf(object content) { if (_parent == null) @@ -172,6 +175,10 @@ namespace Newtonsoft.Json.Linq _parent.AddInternal((Next == null), this, content); } + /// + /// Adds the specified content immediately before this token. + /// + /// A content object that contains simple content or a collection of content objects to be added before this token. public void AddBeforeSelf(object content) { if (_parent == null) @@ -517,7 +524,7 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateFloat(v, true)) throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(v))); - return (v.Value != null) ? (decimal?)Convert.ToDecimal(v.Value) : null; + return (v.Value != null) ? (decimal?)Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture) : null; } /// @@ -613,7 +620,7 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateFloat(v, true)) throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(v))); - return (v.Value != null) ? (float?)Convert.ToSingle(v.Value) : null; + return (v.Value != null) ? (float?)Convert.ToSingle(v.Value, CultureInfo.InvariantCulture) : null; } /// @@ -627,7 +634,7 @@ namespace Newtonsoft.Json.Linq if (v == null || !ValidateFloat(v, false)) throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(v))); - return Convert.ToDecimal(v.Value); + return Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture); } /// @@ -755,6 +762,10 @@ namespace Newtonsoft.Json.Linq get { return this[key]; } } + /// + /// Creates an for this token. + /// + /// An that can be used to read this token and its descendants. public JsonReader CreateReader() { return new JTokenReader(this); @@ -785,11 +796,26 @@ namespace Newtonsoft.Json.Linq return FromObjectInternal(o, new JsonSerializer()); } + /// + /// Creates a from an object using the specified . + /// + /// The object that will be used to create . + /// The that will be used when reading the object. + /// A with the value of the specified object public static JToken FromObject(object o, JsonSerializer jsonSerializer) { return FromObjectInternal(o, jsonSerializer); } + /// + /// Creates a from a . + /// + /// An positioned at the token to read into this . + /// + /// An that contains the token and its descendant tokens + /// that were read from the reader. The runtime type of the token is determined + /// by the token type of the first token encountered in the reader. + /// public static JToken ReadFrom(JsonReader reader) { ValidationUtils.ArgumentNotNull(reader, "reader"); diff --git a/Src/Newtonsoft.Json/Linq/JTokenReader.cs b/Src/Newtonsoft.Json/Linq/JTokenReader.cs index c2640d60..28d99825 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenReader.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenReader.cs @@ -28,7 +28,7 @@ namespace Newtonsoft.Json.Linq } /// - /// Reads the next Json token from the stream. + /// Reads the next JSON token from the stream. /// /// /// true if the next token was read successfully; false if there are no more tokens to read. diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj index 94b464d8..58c468c4 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj @@ -112,10 +112,12 @@ + + @@ -133,6 +135,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj index 28b67180..71ca0d8d 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj @@ -102,15 +102,18 @@ + + + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj index 1ff9fe9b..47cbbbe4 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj @@ -143,6 +143,7 @@ + @@ -160,6 +161,7 @@ + diff --git a/Src/Newtonsoft.Json/PreserveReferencesHandling.cs b/Src/Newtonsoft.Json/PreserveReferencesHandling.cs index afc55cca..e3741077 100644 --- a/Src/Newtonsoft.Json/PreserveReferencesHandling.cs +++ b/Src/Newtonsoft.Json/PreserveReferencesHandling.cs @@ -29,12 +29,27 @@ using System.Text; namespace Newtonsoft.Json { + /// + /// Specifies reference handling options for the . + /// [Flags] public enum PreserveReferencesHandling { + /// + /// Do not preserve references when serializing types. + /// None = 0, + /// + /// Preserve references when serializing into a JSON object structure. + /// Objects = 1, + /// + /// Preserve references when serializing into a JSON array structure. + /// Arrays = 2, + /// + /// Preserve references when serializing. + /// All = Objects | Arrays } } diff --git a/Src/Newtonsoft.Json/ReferenceLoopHandling.cs b/Src/Newtonsoft.Json/ReferenceLoopHandling.cs index 19395f36..4953b958 100644 --- a/Src/Newtonsoft.Json/ReferenceLoopHandling.cs +++ b/Src/Newtonsoft.Json/ReferenceLoopHandling.cs @@ -30,7 +30,7 @@ using System.Text; namespace Newtonsoft.Json { /// - /// Specifies reference loop handling options for the . + /// Specifies reference loop handling options for the . /// public enum ReferenceLoopHandling { diff --git a/Src/Newtonsoft.Json/Schema/Extensions.cs b/Src/Newtonsoft.Json/Schema/Extensions.cs index 9164b34d..054d42d6 100644 --- a/Src/Newtonsoft.Json/Schema/Extensions.cs +++ b/Src/Newtonsoft.Json/Schema/Extensions.cs @@ -32,8 +32,19 @@ using Newtonsoft.Json.Utilities; namespace Newtonsoft.Json.Schema { + /// + /// Contains the JSON schema extension methods. + /// public static class Extensions { + /// + /// Determines whether the is valid. + /// + /// The source to test. + /// The schema to test with. + /// + /// true if the specified is valid; otherwise, false. + /// public static bool IsValid(this JToken source, JsonSchema schema) { bool valid = true; @@ -41,11 +52,22 @@ namespace Newtonsoft.Json.Schema return valid; } + /// + /// Validates the specified . + /// + /// The source to test. + /// The schema to test with. public static void Validate(this JToken source, JsonSchema schema) { source.Validate(schema, null); } + /// + /// Validates the specified . + /// + /// The source to test. + /// The schema to test with. + /// The validation event handler. public static void Validate(this JToken source, JsonSchema schema, ValidationEventHandler validationEventHandler) { ValidationUtils.ArgumentNotNull(source, "source"); diff --git a/Src/Newtonsoft.Json/Schema/JsonSchema.cs b/Src/Newtonsoft.Json/Schema/JsonSchema.cs index 7a71a9a2..25c53188 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchema.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchema.cs @@ -35,35 +35,145 @@ using System.Globalization; namespace Newtonsoft.Json.Schema { + /// + /// An in-memory representation of a JSON Schema. + /// public class JsonSchema { + /// + /// Gets or sets the id. + /// public string Id { get; set; } + /// + /// Gets or sets the title. + /// public string Title { get; set; } + /// + /// Gets or sets whether the object is optional. + /// public bool? Optional { get; set; } + /// + /// Gets or sets whether the object is read only. + /// public bool? ReadOnly { get; set; } + /// + /// Gets or sets whether the object is visible to users. + /// public bool? Hidden { get; set; } + /// + /// Gets or sets whether the object is transient. + /// public bool? Transient { get; set; } + /// + /// Gets or sets the description of the object. + /// public string Description { get; set; } + /// + /// Gets or sets the types of values allowed by the object. + /// + /// The type. public JsonSchemaType? Type { get; set; } + /// + /// Gets or sets the pattern. + /// + /// The pattern. public string Pattern { get; set; } + /// + /// Gets or sets the minimum length. + /// + /// The minimum length. public int? MinimumLength { get; set; } + /// + /// Gets or sets the maximum length. + /// + /// The maximum length. public int? MaximumLength { get; set; } + /// + /// Gets or sets the maximum decimals. + /// + /// The maximum decimals. public int? MaximumDecimals { get; set; } + /// + /// Gets or sets the minimum. + /// + /// The minimum. public double? Minimum { get; set; } + /// + /// Gets or sets the maximum. + /// + /// The maximum. public double? Maximum { get; set; } + /// + /// Gets or sets the minimum number of items. + /// + /// The minimum number of items. public int? MinimumItems { get; set; } + /// + /// Gets or sets the maximum number of items. + /// + /// The maximum number of items. public int? MaximumItems { get; set; } + /// + /// Gets or sets the of items. + /// + /// The of items. public IList Items { get; set; } + /// + /// Gets or sets the of properties. + /// + /// The of properties. public IDictionary Properties { get; set; } + /// + /// Gets or sets the of additional properties. + /// + /// The of additional properties. public JsonSchema AdditionalProperties { get; set; } + /// + /// Gets or sets a value indicating whether additional properties are allowed. + /// + /// + /// true if additional properties are allowed; otherwise, false. + /// public bool AllowAdditionalProperties { get; set; } + /// + /// Gets or sets the required property if this property is present. + /// + /// The required property if this property is present. public string Requires { get; set; } + /// + /// Gets or sets the identity. + /// + /// The identity. public IList Identity { get; set; } + /// + /// Gets or sets the a collection of valid enum values allowed. + /// + /// A collection of valid enum values allowed. public IList Enum { get; set; } + /// + /// Gets or sets a collection of options. + /// + /// A collection of options. public IDictionary Options { get; set; } + /// + /// Gets or sets disallowed types. + /// + /// The disallow types. public JsonSchemaType? Disallow { get; set; } + /// + /// Gets or sets the default value. + /// + /// The default value. public JToken Default { get; set; } + /// + /// Gets or sets the extend . + /// + /// The extended . public JsonSchema Extends { get; set; } + /// + /// Gets or sets the format. + /// + /// The format. public string Format { get; set; } private readonly string _internalId = Guid.NewGuid().ToString("N"); @@ -73,16 +183,30 @@ namespace Newtonsoft.Json.Schema get { return _internalId; } } + /// + /// Initializes a new instance of the class. + /// public JsonSchema() { AllowAdditionalProperties = true; } + /// + /// Reads a from the specified . + /// + /// The containing the JSON Schema to read. + /// The object representing the JSON Schema. public static JsonSchema Read(JsonReader reader) { return Read(reader, new JsonSchemaResolver()); } + /// + /// Reads a from the specified . + /// + /// The containing the JSON Schema to read. + /// The to use when resolving schema references. + /// The object representing the JSON Schema. public static JsonSchema Read(JsonReader reader, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(reader, "reader"); @@ -92,11 +216,22 @@ namespace Newtonsoft.Json.Schema return builder.Parse(reader); } + /// + /// Load a from a string that contains schema JSON. + /// + /// A that contains JSON. + /// A populated from the string that contains JSON. public static JsonSchema Parse(string json) { return Parse(json, new JsonSchemaResolver()); } + /// + /// Parses the specified json. + /// + /// The json. + /// The resolver. + /// public static JsonSchema Parse(string json, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(json, "json"); @@ -106,11 +241,20 @@ namespace Newtonsoft.Json.Schema return Read(reader, resolver); } + /// + /// Writes this schema to a . + /// + /// A into which this method will write. public void WriteTo(JsonWriter writer) { WriteTo(writer, new JsonSchemaResolver()); } + /// + /// Writes this schema to a using the specified . + /// + /// A into which this method will write. + /// The resolver used. public void WriteTo(JsonWriter writer, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(writer, "writer"); @@ -120,6 +264,12 @@ namespace Newtonsoft.Json.Schema schemaWriter.WriteSchema(this); } + /// + /// Returns a that represents the current . + /// + /// + /// A that represents the current . + /// public override string ToString() { StringWriter writer = new StringWriter(CultureInfo.InvariantCulture); diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs index 881cbac4..a0b65e01 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs @@ -32,7 +32,17 @@ namespace Newtonsoft.Json.Schema /// public class JsonSchemaException : Exception { + /// + /// Gets the line number indicating where the error occurred. + /// + /// The line number indicating where the error occurred. public int LineNumber { get; private set; } + + + /// + /// Gets the line position indicating where the error occurred. + /// + /// The line position indicating where the error occurred. public int LinePosition { get; private set; } /// diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs index d0e4e5fd..a3ead62a 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs @@ -34,9 +34,19 @@ using Newtonsoft.Json.Serialization; namespace Newtonsoft.Json.Schema { + /// + /// Generates a from a specified . + /// public class JsonSchemaGenerator { + /// + /// Gets or sets how undefined schemas are handled by the serializer. + /// public UndefinedSchemaIdHandling UndefinedSchemaIdHandling { get; set; } + /// + /// Gets or sets the mapping resolver used by the generator when + /// mapping JSON properties to .NET objet members. + /// public IMappingResolver MappingResolver { get; set; } private class TypeSchema @@ -96,21 +106,45 @@ namespace Newtonsoft.Json.Schema return popped; } + /// + /// Generate a from the specified type. + /// + /// The type to generate a from. + /// A generated from the specified type. public JsonSchema Generate(Type type) { return Generate(type, new JsonSchemaResolver(), false); } + /// + /// Generate a from the specified type. + /// + /// The type to generate a from. + /// The used to resolve schema references. + /// A generated from the specified type. public JsonSchema Generate(Type type, JsonSchemaResolver resolver) { return Generate(type, resolver, false); } + /// + /// Generate a from the specified type. + /// + /// The type to generate a from. + /// Specify whether the generated root will be nullable. + /// A generated from the specified type. public JsonSchema Generate(Type type, bool rootSchemaNullable) { return Generate(type, new JsonSchemaResolver(), rootSchemaNullable); } + /// + /// Generate a from the specified type. + /// + /// The type to generate a from. + /// The used to resolve schema references. + /// Specify whether the generated root will be nullable. + /// A generated from the specified type. public JsonSchema Generate(Type type, JsonSchemaResolver resolver, bool rootSchemaNullable) { ValidationUtils.ArgumentNotNull(type, "type"); @@ -121,7 +155,7 @@ namespace Newtonsoft.Json.Schema return GenerateInternal(type, !rootSchemaNullable); } - public string GetTitle(Type type) + private string GetTitle(Type type) { JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(type); @@ -131,7 +165,7 @@ namespace Newtonsoft.Json.Schema return null; } - public string GetDescription(Type type) + private string GetDescription(Type type) { JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(type); @@ -255,7 +289,7 @@ namespace Newtonsoft.Json.Schema if (mapping.DefaultValue != null) propertySchema.Default = JToken.FromObject(mapping.DefaultValue); - CurrentSchema.Properties.Add(mapping.MappingName, propertySchema); + CurrentSchema.Properties.Add(mapping.PropertyName, propertySchema); } } diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaResolver.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaResolver.cs index 2da7b604..d7c514f2 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaResolver.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaResolver.cs @@ -33,15 +33,30 @@ using Newtonsoft.Json.Utilities; namespace Newtonsoft.Json.Schema { + /// + /// Resolves from an id. + /// public class JsonSchemaResolver { + /// + /// Gets or sets the loaded schemas. + /// + /// The loaded schemas. public IList LoadedSchemas { get; protected set; } + /// + /// Initializes a new instance of the class. + /// public JsonSchemaResolver() { LoadedSchemas = new List(); } + /// + /// Gets a for the specified id. + /// + /// The id. + /// A for the specified id. public virtual JsonSchema GetSchema(string id) { JsonSchema schema = LoadedSchemas.SingleOrDefault(s => s.Id == id); diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaType.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaType.cs index 853f93c2..bf7c1fbe 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaType.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaType.cs @@ -30,17 +30,47 @@ using System.Text; namespace Newtonsoft.Json.Schema { + /// + /// The value types allowed by the . + /// [Flags] public enum JsonSchemaType { + /// + /// No type specified. + /// None = 0, + /// + /// String type. + /// String = 1, + /// + /// Float type. + /// Float = 2, + /// + /// Integer type. + /// Integer = 4, + /// + /// Boolean type. + /// Boolean = 8, + /// + /// Object type. + /// Object = 16, + /// + /// Array type. + /// Array = 32, + /// + /// Null type. + /// Null = 64, + /// + /// Any type. + /// Any = String | Float | Integer | Boolean | Object | Array | Null } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs b/Src/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs index d19adb6a..c38225d7 100644 --- a/Src/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs +++ b/Src/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs @@ -25,10 +25,22 @@ namespace Newtonsoft.Json.Schema { + /// + /// Specifies undefined schema Id handling options for the . + /// public enum UndefinedSchemaIdHandling { + /// + /// Do not infer a schema Id. + /// None = 0, + /// + /// Use the .NET type name as the schema Id. + /// UseTypeName = 1, + /// + /// Use the assembly qualified .NET type name as the schema Id. + /// UseAssemblyQualifiedName = 2, } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Schema/ValidationEventArgs.cs b/Src/Newtonsoft.Json/Schema/ValidationEventArgs.cs index 6952a153..3b2b107a 100644 --- a/Src/Newtonsoft.Json/Schema/ValidationEventArgs.cs +++ b/Src/Newtonsoft.Json/Schema/ValidationEventArgs.cs @@ -28,6 +28,9 @@ using Newtonsoft.Json.Utilities; namespace Newtonsoft.Json.Schema { + /// + /// Returns detailed information related to the . + /// public class ValidationEventArgs : EventArgs { private readonly JsonSchemaException _ex; @@ -38,11 +41,19 @@ namespace Newtonsoft.Json.Schema _ex = ex; } + /// + /// Gets the associated with the validation event. + /// + /// The JsonSchemaException associated with the validation event. public JsonSchemaException Exception { get { return _ex; } } + /// + /// Gets the text description corresponding to the validation event. + /// + /// The text description. public string Message { get { return _ex.Message; } diff --git a/Src/Newtonsoft.Json/Schema/ValidationEventHandler.cs b/Src/Newtonsoft.Json/Schema/ValidationEventHandler.cs index 5b29a737..54315fab 100644 --- a/Src/Newtonsoft.Json/Schema/ValidationEventHandler.cs +++ b/Src/Newtonsoft.Json/Schema/ValidationEventHandler.cs @@ -25,5 +25,8 @@ namespace Newtonsoft.Json.Schema { + /// + /// Represents the callback method that will handle JSON schema validation events and the . + /// public delegate void ValidationEventHandler(object sender, ValidationEventArgs e); } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/CamelCaseMappingResolver.cs b/Src/Newtonsoft.Json/Serialization/CamelCaseMappingResolver.cs index 567e7c5e..74ed0b0b 100644 --- a/Src/Newtonsoft.Json/Serialization/CamelCaseMappingResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/CamelCaseMappingResolver.cs @@ -27,23 +27,32 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Globalization; namespace Newtonsoft.Json.Serialization { + /// + /// Resolves member mappings for a type, camel casing property names. + /// public class CamelCaseMappingResolver : DefaultMappingResolver { - protected override string ResolveMappingName(string mappedName) + /// + /// Resolves the name of the property. + /// + /// Name of the property. + /// + protected override string ResolvePropertyName(string propertyName) { // lower case the first letter of the passed in name - if (string.IsNullOrEmpty(mappedName)) - return mappedName; + if (string.IsNullOrEmpty(propertyName)) + return propertyName; - if (!char.IsUpper(mappedName[0])) - return mappedName; + if (!char.IsUpper(propertyName[0])) + return propertyName; - string camelCaseName = char.ToLower(mappedName[0]).ToString(); - if (mappedName.Length > 1) - camelCaseName += mappedName.Substring(1); + string camelCaseName = char.ToLower(propertyName[0], CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture); + if (propertyName.Length > 1) + camelCaseName += propertyName.Substring(1); return camelCaseName; } diff --git a/Src/Newtonsoft.Json/Serialization/DefaultMappingResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultMappingResolver.cs index f1b55993..39c61e06 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultMappingResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultMappingResolver.cs @@ -26,47 +26,66 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Linq; using System.Reflection; using System.Runtime.Serialization; -using System.Text; using Newtonsoft.Json.Utilities; namespace Newtonsoft.Json.Serialization { + /// + /// Resolves member mappings for a type. + /// public class DefaultMappingResolver : IMappingResolver { internal static readonly IMappingResolver Instance = new DefaultMappingResolver(); - private readonly Dictionary TypeMemberMappingsCache = new Dictionary(); + private readonly Dictionary _typeMemberMappingsCache = new Dictionary(); + /// + /// Gets or sets the default members search flags. + /// + /// The default members search flags. public BindingFlags DefaultMembersSearchFlags { get; set; } + /// + /// Initializes a new instance of the class. + /// public DefaultMappingResolver() { DefaultMembersSearchFlags = BindingFlags.Public | BindingFlags.Instance; } - + + /// + /// Returns a collection of for the specified + /// to be used during serialization. + /// + /// The type to be resolved. + /// A collection of to be used during serialization. public virtual JsonMemberMappingCollection ResolveMappings(Type type) { JsonMemberMappingCollection memberMappings; - if (TypeMemberMappingsCache.TryGetValue(type, out memberMappings)) + if (_typeMemberMappingsCache.TryGetValue(type, out memberMappings)) return memberMappings; // double check locking to avoid threading issues - lock (TypeMemberMappingsCache) + lock (_typeMemberMappingsCache) { - if (TypeMemberMappingsCache.TryGetValue(type, out memberMappings)) + if (_typeMemberMappingsCache.TryGetValue(type, out memberMappings)) return memberMappings; memberMappings = CreateMemberMappings(type); - TypeMemberMappingsCache[type] = memberMappings; + _typeMemberMappingsCache[type] = memberMappings; return memberMappings; } } + /// + /// Gets the serializable members for the type. + /// + /// The type to get serializable members for. + /// The serializable members for the type. protected virtual List GetSerializableMembers(Type objectType) { #if !PocketPC @@ -118,6 +137,12 @@ namespace Newtonsoft.Json.Serialization return memberMappings; } + /// + /// Creates a for the given . + /// + /// The member's declaring type member serialization mode. + /// The member to create a for. + /// A created for the given . protected virtual JsonMemberMapping CreateMemberMapping(MemberSerialization memberSerialization, MemberInfo member) { JsonObjectAttribute jsonObjectAttribute = JsonTypeReflector.GetJsonContainerAttribute(member.DeclaringType) as JsonObjectAttribute; @@ -145,7 +170,7 @@ namespace Newtonsoft.Json.Serialization else mappedName = member.Name; - string resolvedMappedName = ResolveMappingName(mappedName); + string resolvedMappedName = ResolvePropertyName(mappedName); bool required; if (propertyAttribute != null) @@ -186,9 +211,14 @@ namespace Newtonsoft.Json.Serialization return new JsonMemberMapping(resolvedMappedName, member, ignored, readable, writable, memberConverter, defaultValue, required, isReference, nullValueHandling, defaultValueHandling, referenceLoopHandling); } - protected virtual string ResolveMappingName(string mappedName) + /// + /// Resolves the name of the property. + /// + /// Name of the property. + /// + protected virtual string ResolvePropertyName(string propertyName) { - return mappedName; + return propertyName; } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs index 812278f4..f8db3fff 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -48,14 +48,14 @@ namespace Newtonsoft.Json.Serialization } } - public object ResolveObject(string reference) + public object ResolveReference(string reference) { object value; Mappings.TryGetByFirst(reference, out value); return value; } - public string ResolveReference(object value) + public string GetReference(object value) { string reference; if (!Mappings.TryGetBySecond(value, out reference)) @@ -68,12 +68,12 @@ namespace Newtonsoft.Json.Serialization return reference; } - public void AddObjectReference(string reference, object value) + public void AddReference(string reference, object value) { Mappings.Add(reference, value); } - public bool HasObjectReference(object value) + public bool IsReferenced(object value) { string reference; return Mappings.TryGetBySecond(value, out reference); diff --git a/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs b/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs new file mode 100644 index 00000000..5f760a7b --- /dev/null +++ b/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs @@ -0,0 +1,44 @@ +using System; +using System.Runtime.Serialization; +using System.Reflection; +using System.Globalization; +using Newtonsoft.Json.Utilities; + +namespace Newtonsoft.Json.Serialization +{ + /// + /// The default serialization binder used when resolving and loading classes from type names. + /// + public class DefaultSerializationBinder : SerializationBinder + { + internal static readonly DefaultSerializationBinder Instance = new DefaultSerializationBinder(); + + /// + /// When overridden in a derived class, controls the binding of a serialized object to a type. + /// + /// Specifies the name of the serialized object. + /// Specifies the name of the serialized object. + /// + /// The type of the object the formatter creates a new instance of. + /// + public override Type BindToType(string assemblyName, string typeName) + { + if (assemblyName != null) + { + Assembly assembly = Assembly.Load(assemblyName); + if (assembly == null) + throw new JsonSerializationException("Could not load assembly '{0}'.".FormatWith(CultureInfo.InvariantCulture, assemblyName)); + + Type type = assembly.GetType(typeName); + if (type == null) + throw new JsonSerializationException("Could not find type '{0}'.".FormatWith(CultureInfo.InvariantCulture, typeName)); + + return type; + } + else + { + return Type.GetType(typeName); + } + } + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/IMappingResolver.cs b/Src/Newtonsoft.Json/Serialization/IMappingResolver.cs index 685e9c28..2cdadfcd 100644 --- a/Src/Newtonsoft.Json/Serialization/IMappingResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/IMappingResolver.cs @@ -37,7 +37,7 @@ namespace Newtonsoft.Json.Serialization { /// /// Returns a collection of for the specified - /// to be used during serialization. + /// to be used during serialization. /// /// The type to be resolved. /// A collection of to be used during serialization. diff --git a/Src/Newtonsoft.Json/Serialization/IReferenceResolver.cs b/Src/Newtonsoft.Json/Serialization/IReferenceResolver.cs index 81bf8df9..3288f064 100644 --- a/Src/Newtonsoft.Json/Serialization/IReferenceResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/IReferenceResolver.cs @@ -25,11 +25,36 @@ namespace Newtonsoft.Json.Serialization { + /// + /// Used to resolve references when serializing and deserializing JSON by the . + /// public interface IReferenceResolver { - object ResolveObject(string reference); - string ResolveReference(object value); - bool HasObjectReference(object value); - void AddObjectReference(string reference, object value); + /// + /// Resolves the reference to its object. + /// + /// The reference to resolve. + /// The object that + object ResolveReference(string reference); + /// + /// Gets the reference for the sepecified object. + /// + /// The object to get a reference for. + /// The reference to the object. + string GetReference(object value); + /// + /// Determines whether the specified object is referenced. + /// + /// The object to test for a reference. + /// + /// true if the specified object is referenced; otherwise, false. + /// + bool IsReferenced(object value); + /// + /// Adds a reference to the specified object. + /// + /// The reference. + /// The object to reference. + void AddReference(string reference, object value); } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonMemberMapping.cs b/Src/Newtonsoft.Json/Serialization/JsonMemberMapping.cs index 221d068b..5fed024b 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonMemberMapping.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonMemberMapping.cs @@ -23,16 +23,16 @@ // OTHER DEALINGS IN THE SOFTWARE. #endregion -using System; -using System.Collections.Generic; -using System.Text; using System.Reflection; namespace Newtonsoft.Json.Serialization { + /// + /// Maps a JSON property to a .NET member. + /// public class JsonMemberMapping { - private readonly string _mappingName; + private readonly string _propertyName; private readonly MemberInfo _member; private readonly bool _ignored; private readonly bool _readable; @@ -45,9 +45,24 @@ namespace Newtonsoft.Json.Serialization private readonly DefaultValueHandling? _defaultValueHandling; private readonly ReferenceLoopHandling? _referenceLoopHandling; - public JsonMemberMapping(string mappingName, MemberInfo member, bool ignored, bool readable, bool writable, JsonConverter memberConverter, object defaultValue, bool required, bool isReference, NullValueHandling? nullValueHandling, DefaultValueHandling? defaultValueHandling, ReferenceLoopHandling? referenceLoopHandling) + /// + /// Initializes a new instance of the class. + /// + /// Name of the property. + /// The member. + /// If set to true mapping is ignored during serialization. + /// If set to true mapping is readable. + /// If set to true mapping is writable. + /// The member converter to use during serialization. + /// The mapping default value. + /// If set to true mapping is required during serialization. + /// If set to true mapping preserve reference. + /// Mapping null value handling. + /// Mapping default value handling. + /// Mapping reference loop handling. + public JsonMemberMapping(string propertyName, MemberInfo member, bool ignored, bool readable, bool writable, JsonConverter memberConverter, object defaultValue, bool required, bool isReference, NullValueHandling? nullValueHandling, DefaultValueHandling? defaultValueHandling, ReferenceLoopHandling? referenceLoopHandling) { - _mappingName = mappingName; + _propertyName = propertyName; _member = member; _ignored = ignored; _readable = readable; @@ -61,61 +76,111 @@ namespace Newtonsoft.Json.Serialization _referenceLoopHandling = referenceLoopHandling; } - public string MappingName + /// + /// Gets the name of the property. + /// + /// The name of the property. + public string PropertyName { - get { return _mappingName; } + get { return _propertyName; } } + /// + /// Gets the member. + /// + /// The member. public MemberInfo Member { get { return _member; } } + /// + /// Gets a value indicating whether this is ignored. + /// + /// true if ignored; otherwise, false. public bool Ignored { get { return _ignored; } } + /// + /// Gets a value indicating whether this is readable. + /// + /// true if readable; otherwise, false. public bool Readable { get { return _readable; } } + /// + /// Gets a value indicating whether this is writable. + /// + /// true if writable; otherwise, false. public bool Writable { get { return _writable; } } + /// + /// Gets the member converter. + /// + /// The member converter. public JsonConverter MemberConverter { get { return _memberConverter; } } + /// + /// Gets the default value. + /// + /// The default value. public object DefaultValue { get { return _defaultValue; } } + /// + /// Gets a value indicating whether this is required. + /// + /// true if required; otherwise, false. public bool Required { get { return _required; } } + /// + /// Gets a value indicating whether this mapping preserves object references. + /// + /// + /// true if this instance is reference; otherwise, false. + /// public bool IsReference { get { return _isReference; } } + /// + /// Gets the mapping null value handling. + /// + /// The null value handling. public NullValueHandling? NullValueHandling { get { return _nullValueHandling; } } + /// + /// Gets the mapping default value handling. + /// + /// The default value handling. public DefaultValueHandling? DefaultValueHandling { get { return _defaultValueHandling; } } + /// + /// Gets the mapping reference loop handling. + /// + /// The reference loop handling. public ReferenceLoopHandling? ReferenceLoopHandling { get { return _referenceLoopHandling; } diff --git a/Src/Newtonsoft.Json/Serialization/JsonMemberMappingCollection.cs b/Src/Newtonsoft.Json/Serialization/JsonMemberMappingCollection.cs index 11f90808..79749643 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonMemberMappingCollection.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonMemberMappingCollection.cs @@ -32,27 +32,39 @@ using System.Globalization; namespace Newtonsoft.Json.Serialization { + /// + /// A collection of objects. + /// public class JsonMemberMappingCollection : KeyedCollection { + /// + /// When implemented in a derived class, extracts the key from the specified element. + /// + /// The element from which to extract the key. + /// The key for the specified element. protected override string GetKeyForItem(JsonMemberMapping item) { - return item.MappingName; + return item.PropertyName; } + /// + /// Adds a object. + /// + /// The member mapping to add to the collection. public void AddMapping(JsonMemberMapping memberMapping) { - if (Contains(memberMapping.MappingName)) + if (Contains(memberMapping.PropertyName)) { // don't overwrite existing mapping with ignored mapping if (memberMapping.Ignored) return; - JsonMemberMapping existingMemberMapping = this[memberMapping.MappingName]; + JsonMemberMapping existingMemberMapping = this[memberMapping.PropertyName]; if (!existingMemberMapping.Ignored) { throw new JsonSerializationException( - "A member with the name '{0}' already exists on {1}. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, memberMapping.MappingName, memberMapping.Member.DeclaringType)); + "A member with the name '{0}' already exists on {1}. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, memberMapping.PropertyName, memberMapping.Member.DeclaringType)); } else { @@ -64,21 +76,36 @@ namespace Newtonsoft.Json.Serialization Add(memberMapping); } - public bool TryGetClosestMatchMapping(string mappingName, out JsonMemberMapping memberMapping) + /// + /// Tries to get the closest matching object. + /// First attempts to get an exact case match of propertyName and then + /// a case insensitive match. + /// + /// Name of the mapping. + /// The member mapping. + /// + public bool TryGetClosestMatchMapping(string propertyName, out JsonMemberMapping memberMapping) { - if (TryGetMapping(mappingName, StringComparison.Ordinal, out memberMapping)) + if (TryGetMapping(propertyName, StringComparison.Ordinal, out memberMapping)) return true; - if (TryGetMapping(mappingName, StringComparison.OrdinalIgnoreCase, out memberMapping)) + if (TryGetMapping(propertyName, StringComparison.OrdinalIgnoreCase, out memberMapping)) return true; return false; } - public bool TryGetMapping(string mappingName, StringComparison comparisonType, out JsonMemberMapping memberMapping) + /// + /// Tries to get a member mapping by property name. + /// + /// The property name of the member mapping to get. + /// Type property name compare string comparison. + /// The member mapping. + /// + public bool TryGetMapping(string propertyName, StringComparison comparisonType, out JsonMemberMapping memberMapping) { foreach (JsonMemberMapping mapping in this) { - if (string.Compare(mappingName, mapping.MappingName, comparisonType) == 0) + if (string.Compare(propertyName, mapping.PropertyName, comparisonType) == 0) { memberMapping = mapping; return true; diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs index dae47454..d8a304e1 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs @@ -25,6 +25,7 @@ using System; using Newtonsoft.Json.Utilities; +using System.Runtime.Serialization; namespace Newtonsoft.Json.Serialization { @@ -87,6 +88,18 @@ namespace Newtonsoft.Json.Serialization set { _serializer.PreserveReferencesHandling = value; } } + public override TypeNameHandling TypeNameHandling + { + get { return _serializer.TypeNameHandling; } + set { _serializer.TypeNameHandling = value; } + } + + public override SerializationBinder Binder + { + get { return _serializer.Binder; } + set { _serializer.Binder = value; } + } + public JsonSerializerProxy(JsonSerializerReader serializerReader) { ValidationUtils.ArgumentNotNull(serializerReader, "serializerReader"); diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerReader.cs index c5077614..6307d21c 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerReader.cs @@ -62,13 +62,20 @@ namespace Newtonsoft.Json.Serialization } else if (reader.TokenType == JsonToken.StartObject) { - if (!reader.Read()) - throw new JsonSerializationException("Unexpected end when deserializing object."); + CheckedRead(reader); + + string id = null; + if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.IdPropertyName, StringComparison.Ordinal)) + { + CheckedRead(reader); + id = reader.Value.ToString(); + CheckedRead(reader); + } if (CollectionUtils.IsDictionaryType(objectType)) - PopulateDictionary(CollectionUtils.CreateDictionaryWrapper(target), reader); + PopulateDictionary(CollectionUtils.CreateDictionaryWrapper(target), reader, id); else - PopulateObject(target, reader, objectType); + PopulateObject(target, reader, objectType, id); } } @@ -80,10 +87,7 @@ namespace Newtonsoft.Json.Serialization if (!reader.Read()) return null; - if (objectType != null) - return CreateValue(reader, objectType, null, null); - else - return CreateJToken(reader); + return CreateValue(reader, objectType, null, null); } private JsonSerializerProxy GetInternalSerializer() @@ -96,6 +100,8 @@ namespace Newtonsoft.Json.Serialization private JToken CreateJToken(JsonReader reader) { + ValidationUtils.ArgumentNotNull(reader, "reader"); + JToken token; using (JTokenWriter writer = new JTokenWriter()) { @@ -106,6 +112,28 @@ namespace Newtonsoft.Json.Serialization return token; } + private JToken CreateJObject(JsonReader reader) + { + ValidationUtils.ArgumentNotNull(reader, "reader"); + +// throw new Exception("Expected current token of type {0}, got {1}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.PropertyName, reader.TokenType)); + + JToken token; + using (JTokenWriter writer = new JTokenWriter()) + { + writer.WriteStartObject(); + + if (reader.TokenType == JsonToken.PropertyName) + writer.WriteToken(reader, reader.Depth - 1); + else + writer.WriteEndObject(); + + token = writer.Token; + } + + return token; + } + private object CreateValue(JsonReader reader, Type objectType, object existingValue, JsonConverter memberConverter) { object value; @@ -134,47 +162,111 @@ namespace Newtonsoft.Json.Serialization // populate a typed object or generic dictionary/array // depending upon whether an objectType was supplied case JsonToken.StartObject: - if (objectType == null) - { - value = CreateJToken(reader); - } - else - { - CheckedRead(reader); + CheckedRead(reader); - if (reader.TokenType == JsonToken.PropertyName) + string id = null; + + if (reader.TokenType == JsonToken.PropertyName) + { + bool specialProperty; + + do { string propertyName = reader.Value.ToString(); if (string.Equals(propertyName, JsonTypeReflector.RefPropertyName, StringComparison.Ordinal)) { CheckedRead(reader); - string id = reader.Value.ToString(); + string reference = reader.Value.ToString(); CheckedRead(reader); - return _serializer.ReferenceResolver.ResolveObject(id); + return _serializer.ReferenceResolver.ResolveReference(reference); } - else if (string.Equals(propertyName, JsonTypeReflector.IdPropertyName, StringComparison.Ordinal) - && !CollectionUtils.IsDictionaryType(objectType) - && CollectionUtils.IsListType(objectType)) + else if (string.Equals(propertyName, JsonTypeReflector.TypePropertyName, StringComparison.Ordinal)) { - return CreateReferencedList(reader, objectType, existingValue); - } - } + CheckedRead(reader); + string qualifiedTypeName = reader.Value.ToString(); + CheckedRead(reader); + + if (_serializer.TypeNameHandling != TypeNameHandling.None) + { + int delimiterIndex = qualifiedTypeName.IndexOf(','); + string typeName; + string assemblyName; + if (delimiterIndex != -1) + { + typeName = qualifiedTypeName.Substring(0, delimiterIndex).Trim(); + assemblyName = qualifiedTypeName.Substring(delimiterIndex + 1, qualifiedTypeName.Length - delimiterIndex - 1).Trim(); + } + else + { + typeName = qualifiedTypeName; + assemblyName = null; + } + + Type specifiedType; + try + { + specifiedType = _serializer.Binder.BindToType(assemblyName, typeName); + } + catch (Exception ex) + { + throw new JsonSerializationException("Error resolving type specified in JSON '{0}'.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName), ex); + } + + if (specifiedType == null) + throw new JsonSerializationException("Type specified in JSON '{0}' was not resolved.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName)); + + if (objectType != null && !objectType.IsAssignableFrom(specifiedType)) + throw new JsonSerializationException("Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, specifiedType.AssemblyQualifiedName, objectType.AssemblyQualifiedName)); + + objectType = specifiedType; + } + specialProperty = true; + } + else if (string.Equals(propertyName, JsonTypeReflector.IdPropertyName, StringComparison.Ordinal)) + { + CheckedRead(reader); + + id = reader.Value.ToString(); + CheckedRead(reader); + specialProperty = true; + } + else if (string.Equals(propertyName, JsonTypeReflector.ArrayValuesPropertyName, StringComparison.Ordinal)) + { + CheckedRead(reader); + object list = CreateList(reader, objectType, existingValue, id); + CheckedRead(reader); + return list; + } + else + { + specialProperty = false; + } + } while (specialProperty + && reader.TokenType == JsonToken.PropertyName); + } + + if (objectType == null) + { + value = CreateJObject(reader); + } + else + { if (CollectionUtils.IsDictionaryType(objectType)) { if (existingValue == null) - value = CreateAndPopulateDictionary(reader, objectType); + value = CreateAndPopulateDictionary(reader, objectType, id); else - value = PopulateDictionary(CollectionUtils.CreateDictionaryWrapper(existingValue), reader); + value = PopulateDictionary(CollectionUtils.CreateDictionaryWrapper(existingValue), reader, id); } else { if (existingValue == null) - value = CreateAndPopulateObject(reader, objectType); + value = CreateAndPopulateObject(reader, objectType, id); else - value = PopulateObject(existingValue, reader, objectType); + value = PopulateObject(existingValue, reader, objectType, id); } } break; @@ -215,27 +307,6 @@ namespace Newtonsoft.Json.Serialization throw new JsonSerializationException("Unexpected end when deserializing object."); } - private object CreateReferencedList(JsonReader reader, Type objectType, object existingValue) - { - object value; - - CheckedRead(reader); - string id = reader.Value.ToString(); - - CheckedRead(reader); - if (reader.TokenType != JsonToken.PropertyName && reader.Value.ToString() != "value") - throw new JsonSerializationException("Error reading referenced list."); - - CheckedRead(reader); - if (reader.TokenType != JsonToken.StartArray) - throw new JsonSerializationException("Error reading referenced list."); - - value = CreateList(reader, objectType, existingValue, id); - - CheckedRead(reader); - return value; - } - private object CreateList(JsonReader reader, Type objectType, object existingValue, string reference) { object value; @@ -344,7 +415,7 @@ namespace Newtonsoft.Json.Serialization return true; } - private object CreateAndPopulateDictionary(JsonReader reader, Type objectType) + private object CreateAndPopulateDictionary(JsonReader reader, Type objectType, string id) { if (IsTypeGenericDictionaryInterface(objectType)) { @@ -355,34 +426,30 @@ namespace Newtonsoft.Json.Serialization } IWrappedDictionary dictionary = CollectionUtils.CreateDictionaryWrapper(Activator.CreateInstance(objectType)); - PopulateDictionary(dictionary, reader); + + PopulateDictionary(dictionary, reader, id); return dictionary.UnderlyingDictionary; } - private IDictionary PopulateDictionary(IWrappedDictionary dictionary, JsonReader reader) + private IDictionary PopulateDictionary(IWrappedDictionary dictionary, JsonReader reader, string id) { Type dictionaryType = dictionary.UnderlyingDictionary.GetType(); Type dictionaryKeyType = ReflectionUtils.GetDictionaryKeyType(dictionaryType); Type dictionaryValueType = ReflectionUtils.GetDictionaryValueType(dictionaryType); + if (id != null) + _serializer.ReferenceResolver.AddReference(id, dictionary.UnderlyingDictionary); + do { switch (reader.TokenType) { case JsonToken.PropertyName: - if (reader.Value is string && string.Equals(reader.Value.ToString(), JsonTypeReflector.IdPropertyName, StringComparison.Ordinal)) - { - reader.Read(); - _serializer.ReferenceResolver.AddObjectReference(reader.Value.ToString(), dictionary.UnderlyingDictionary); - } - else - { - object keyValue = EnsureType(reader.Value, dictionaryKeyType); - reader.Read(); + object keyValue = EnsureType(reader.Value, dictionaryKeyType); + CheckedRead(reader); - dictionary.Add(keyValue, CreateValue(reader, dictionaryValueType, null, null)); - } + dictionary.Add(keyValue, CreateValue(reader, dictionaryValueType, null, null)); break; case JsonToken.EndObject: return dictionary; @@ -414,7 +481,7 @@ namespace Newtonsoft.Json.Serialization private IList PopulateList(IList list, Type listItemType, JsonReader reader, string reference) { if (reference != null) - _serializer.ReferenceResolver.AddObjectReference(reference, list); + _serializer.ReferenceResolver.AddReference(reference, list); while (reader.Read()) { @@ -457,7 +524,7 @@ namespace Newtonsoft.Json.Serialization || genericDefinition == typeof(IEnumerable<>)); } - private object CreateAndPopulateObject(JsonReader reader, Type objectType) + private object CreateAndPopulateObject(JsonReader reader, Type objectType, string id) { object newObject; @@ -468,7 +535,7 @@ namespace Newtonsoft.Json.Serialization { newObject = Activator.CreateInstance(objectType); - PopulateObject(newObject, reader, objectType); + PopulateObject(newObject, reader, objectType, id); return newObject; } @@ -529,7 +596,7 @@ namespace Newtonsoft.Json.Serialization foreach (KeyValuePair mappingValue in mappingValues) { - ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, mappingValue.Key.MappingName).Key; + ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, mappingValue.Key.PropertyName).Key; if (matchingConstructorParameter != null) constructorParameters[matchingConstructorParameter] = mappingValue.Value; else @@ -548,11 +615,14 @@ namespace Newtonsoft.Json.Serialization return createdObject; } - private object PopulateObject(object newObject, JsonReader reader, Type objectType) + private object PopulateObject(object newObject, JsonReader reader, Type objectType, string id) { JsonMemberMappingCollection memberMappings = _serializer.GetMemberMappings(objectType); Dictionary requiredMappings = - memberMappings.Where(m => m.Required).ToDictionary(m => m.MappingName, m => false); + memberMappings.Where(m => m.Required).ToDictionary(m => m.PropertyName, m => false); + + if (id != null) + _serializer.ReferenceResolver.AddReference(id, newObject); do { @@ -564,17 +634,10 @@ namespace Newtonsoft.Json.Serialization if (!reader.Read()) throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); - if (string.Equals(memberName, JsonTypeReflector.IdPropertyName, StringComparison.Ordinal)) - { - _serializer.ReferenceResolver.AddObjectReference(reader.Value.ToString(), newObject); - } - else - { - if (reader.TokenType != JsonToken.Null) - SetRequiredMapping(memberName, requiredMappings); - - SetObjectMember(reader, newObject, objectType, memberName); - } + if (reader.TokenType != JsonToken.Null) + SetRequiredMapping(memberName, requiredMappings); + + SetObjectMember(reader, newObject, objectType, memberName); break; case JsonToken.EndObject: foreach (KeyValuePair requiredMapping in requiredMappings) diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerWriter.cs index 5ece158f..753af484 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerWriter.cs @@ -144,13 +144,13 @@ namespace Newtonsoft.Json.Serialization if (!isReference.Value) return false; - return _serializer.ReferenceResolver.HasObjectReference(value); + return _serializer.ReferenceResolver.IsReferenced(value); } private void WriteMemberInfoProperty(JsonWriter writer, object value, JsonMemberMapping memberMapping) { MemberInfo member = memberMapping.Member; - string propertyName = memberMapping.MappingName; + string propertyName = memberMapping.PropertyName; JsonConverter memberConverter = memberMapping.MemberConverter; object defaultValue = memberMapping.DefaultValue; @@ -203,7 +203,7 @@ namespace Newtonsoft.Json.Serialization { writer.WriteStartObject(); writer.WritePropertyName(JsonTypeReflector.RefPropertyName); - writer.WriteValue(_serializer.ReferenceResolver.ResolveReference(value)); + writer.WriteValue(_serializer.ReferenceResolver.GetReference(value)); writer.WriteEndObject(); } @@ -240,7 +240,11 @@ namespace Newtonsoft.Json.Serialization if (isReference) { writer.WritePropertyName(JsonTypeReflector.IdPropertyName); - writer.WriteValue(_serializer.ReferenceResolver.ResolveReference(value)); + writer.WriteValue(_serializer.ReferenceResolver.GetReference(value)); + } + if (HasFlag(_serializer.TypeNameHandling, TypeNameHandling.Objects)) + { + WriteTypeProperty(writer, objectType); } JsonMemberMappingCollection memberMappings = _serializer.GetMemberMappings(objectType); @@ -255,11 +259,22 @@ namespace Newtonsoft.Json.Serialization SerializeStack.RemoveAt(SerializeStack.Count - 1); } + private void WriteTypeProperty(JsonWriter writer, Type type) + { + writer.WritePropertyName(JsonTypeReflector.TypePropertyName); + writer.WriteValue(type.AssemblyQualifiedName); + } + private bool HasFlag(PreserveReferencesHandling value, PreserveReferencesHandling flag) { return ((value & flag) == flag); } + private bool HasFlag(TypeNameHandling value, TypeNameHandling flag) + { + return ((value & flag) == flag); + } + private bool? IsReference(Type t) { JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(t); @@ -298,13 +313,22 @@ namespace Newtonsoft.Json.Serialization SerializeStack.Add(values); bool isReference = IsReference(values.GetType()) ?? HasFlag(_serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays); - if (isReference) + bool includeTypeDetails = HasFlag(_serializer.TypeNameHandling, TypeNameHandling.Arrays); + + if (isReference || includeTypeDetails) { writer.WriteStartObject(); - writer.WritePropertyName(JsonTypeReflector.IdPropertyName); - writer.WriteValue(_serializer.ReferenceResolver.ResolveReference(values)); - writer.WritePropertyName("value"); + if (isReference) + { + writer.WritePropertyName(JsonTypeReflector.IdPropertyName); + writer.WriteValue(_serializer.ReferenceResolver.GetReference(values)); + } + if (includeTypeDetails) + { + WriteTypeProperty(writer, values.GetType()); + } + writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName); } writer.WriteStartArray(); @@ -345,7 +369,11 @@ namespace Newtonsoft.Json.Serialization if (isReference) { writer.WritePropertyName(JsonTypeReflector.IdPropertyName); - writer.WriteValue(_serializer.ReferenceResolver.ResolveReference(values)); + writer.WriteValue(_serializer.ReferenceResolver.GetReference(values)); + } + if (HasFlag(_serializer.TypeNameHandling, TypeNameHandling.Objects)) + { + WriteTypeProperty(writer, values.GetType()); } foreach (DictionaryEntry entry in values) diff --git a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs index 50598825..aa3241d1 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs @@ -40,6 +40,8 @@ namespace Newtonsoft.Json.Serialization { public const string IdPropertyName = "$id"; public const string RefPropertyName = "$ref"; + public const string TypePropertyName = "$type"; + public const string ArrayValuesPropertyName = "$values"; private static readonly Dictionary ConverterTypeCache = new Dictionary(); private static readonly Dictionary AssociatedMetadataTypesCache = new Dictionary(); diff --git a/Src/Newtonsoft.Json/SerializationBinder.cs b/Src/Newtonsoft.Json/SerializationBinder.cs new file mode 100644 index 00000000..9f55569a --- /dev/null +++ b/Src/Newtonsoft.Json/SerializationBinder.cs @@ -0,0 +1,21 @@ +#if SILVERLIGHT || PocketPC +using System; +using System.Reflection; + +namespace Newtonsoft.Json +{ + /// + /// Allows users to control class loading and mandate what class to load. + /// + public abstract class SerializationBinder + { + /// + /// When overridden in a derived class, controls the binding of a serialized object to a type. + /// + /// Specifies the name of the serialized object. + /// Specifies the name of the serialized object + /// + public abstract Type BindToType(string assemblyName, string typeName); + } +} +#endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json/TypeNameHandling.cs b/Src/Newtonsoft.Json/TypeNameHandling.cs new file mode 100644 index 00000000..d6ddd52d --- /dev/null +++ b/Src/Newtonsoft.Json/TypeNameHandling.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Newtonsoft.Json +{ + /// + /// Specifies type name handling options for the . + /// + [Flags] + public enum TypeNameHandling + { + /// + /// Do not include the .NET type name when serializing types. + /// + None = 0, + /// + /// Include the .NET type name when serializing into a JSON object structure. + /// + Objects = 1, + /// + /// Include the .NET type name when serializing into a JSON array structure. + /// + Arrays = 2, + /// + /// Always include the .NET type name when serializing. + /// + All = Objects | Arrays + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/EnumUtils.cs b/Src/Newtonsoft.Json/Utilities/EnumUtils.cs index e14dee3b..e40c80e4 100644 --- a/Src/Newtonsoft.Json/Utilities/EnumUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/EnumUtils.cs @@ -72,7 +72,7 @@ namespace Newtonsoft.Json.Utilities Type underlyingType = Enum.GetUnderlyingType(value.GetType()); - ulong num = Convert.ToUInt64(value); + ulong num = Convert.ToUInt64(value, CultureInfo.InvariantCulture); EnumValues enumNameValues = GetNamesAndValues(); IList selectedFlagsValues = new List(); @@ -134,8 +134,8 @@ namespace Newtonsoft.Json.Utilities catch (OverflowException e) { throw new Exception( - string.Format("Value from enum with the underlying type of {0} cannot be added to dictionary with a value type of {1}. Value was too large: {2}", - Enum.GetUnderlyingType(enumType), typeof(TUnderlyingType), Convert.ToUInt64(enumValues[i])), e); + string.Format(CultureInfo.InvariantCulture, "Value from enum with the underlying type of {0} cannot be added to dictionary with a value type of {1}. Value was too large: {2}", + Enum.GetUnderlyingType(enumType), typeof(TUnderlyingType), Convert.ToUInt64(enumValues[i], CultureInfo.InvariantCulture)), e); } } @@ -206,7 +206,7 @@ namespace Newtonsoft.Json.Utilities Type enumUnderlyingType = Enum.GetUnderlyingType(enumType); if (!typeof(TEnumType).IsAssignableFrom(enumUnderlyingType)) - throw new ArgumentException(string.Format("TEnumType is not assignable from the enum's underlying type of {0}.", enumUnderlyingType.Name)); + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "TEnumType is not assignable from the enum's underlying type of {0}.", enumUnderlyingType.Name)); ulong maximumValue = 0; IList enumValues = GetValues(enumType);