diff --git a/Src/Doc/SerializingJSON.html b/Src/Doc/SerializingJSON.html
index 26f40079..9307c5cb 100644
--- a/Src/Doc/SerializingJSON.html
+++ b/Src/Doc/SerializingJSON.html
@@ -87,6 +87,9 @@
NullValueHandling
Controls how null values are handled during serialization and deserialization.
Include or ignore.
+DefaultValueHandling
+Controls whether a value will be written to JSON or not if it matches the value specified in
+the member's DefaultValueAttribute. Include or ignore.
ObjectCreationHandling
Controls how objects are created during deserialization. Auto, reuse, replace.
Converters
diff --git a/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs
index 19ac5754..26dde0a9 100644
--- a/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs
@@ -27,6 +27,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using Newtonsoft.Json.Tests.TestObjects;
using NUnit.Framework;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Utilities;
diff --git a/Src/Newtonsoft.Json.Tests/Converters/JavaScriptDateTimeConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/JavaScriptDateTimeConverterTests.cs
index db5eacf5..31a947ea 100644
--- a/Src/Newtonsoft.Json.Tests/Converters/JavaScriptDateTimeConverterTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Converters/JavaScriptDateTimeConverterTests.cs
@@ -27,6 +27,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using Newtonsoft.Json.Tests.TestObjects;
using NUnit.Framework;
using Newtonsoft.Json.Converters;
diff --git a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
index 799bdf28..e7b59df5 100644
--- a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
@@ -274,5 +274,22 @@ now brown cow?", '"', true);
object u = JsonConvert.DeserializeObject("undefined");
Assert.AreEqual(null, u);
}
+
+ [Test]
+ public void FloatToString()
+ {
+ Assert.AreEqual("1.1", JsonConvert.ToString(1.1));
+ Assert.AreEqual("1.11", JsonConvert.ToString(1.11));
+ Assert.AreEqual("1.111", JsonConvert.ToString(1.111));
+ Assert.AreEqual("1.1111", JsonConvert.ToString(1.1111));
+ Assert.AreEqual("1.11111", JsonConvert.ToString(1.11111));
+ Assert.AreEqual("1.111111", JsonConvert.ToString(1.111111));
+ Assert.AreEqual("1.0", JsonConvert.ToString(1.0));
+ Assert.AreEqual("1.01", JsonConvert.ToString(1.01));
+ Assert.AreEqual("1.001", JsonConvert.ToString(1.001));
+ Assert.AreEqual(JsonConvert.PositiveInfinity, JsonConvert.ToString(double.PositiveInfinity));
+ Assert.AreEqual(JsonConvert.NegativeInfinity, JsonConvert.ToString(double.NegativeInfinity));
+ Assert.AreEqual(JsonConvert.NaN, JsonConvert.ToString(double.NaN));
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs
index 388e1c83..c1bd43cb 100644
--- a/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs
@@ -39,183 +39,10 @@ using Newtonsoft.Json.Converters;
#if !PocketPC
using System.Runtime.Serialization.Json;
#endif
-using Newtonsoft.Json.Utilities;
-using System.Globalization;
-using System.ComponentModel;
+using Newtonsoft.Json.Tests.TestObjects;
namespace Newtonsoft.Json.Tests
{
- public class Product
- {
- public string Name;
- public DateTime Expiry = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
- public decimal Price;
- public string[] Sizes;
-
- public override bool Equals(object obj)
- {
- if (obj is Product)
- {
- Product p = (Product)obj;
-
- return (p.Name == Name && p.Expiry == Expiry && p.Price == Price);
- }
-
- return base.Equals(obj);
- }
-
- public override int GetHashCode()
- {
- return (Name ?? string.Empty).GetHashCode();
- }
- }
-
- public class ProductCollection : List
- {
- }
-
- public class ProductShort
- {
- public string Name;
- public DateTime Expiry;
- //public decimal Price;
- public string[] Sizes;
- }
-
- public class Store
- {
- public StoreColor Color = StoreColor.Yellow;
- public DateTimeOffset Establised = new DateTimeOffset(2010, 1, 22, 1, 1, 1, TimeSpan.Zero);
- public double Width = 1.1;
- public int Employees = 999;
- public int[] RoomsPerFloor = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
- public bool Open = false;
- public char Symbol = '@';
- public List Mottos = new List();
- public decimal Cost = 100980.1M;
- public string Escape = "\r\n\t\f\b?{\\r\\n\"\'";
- public List product = new List();
-
- public Store()
- {
- Mottos.Add("Hello World");
- Mottos.Add("öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~");
- Mottos.Add(null);
- Mottos.Add(" ");
-
- Product rocket = new Product();
- rocket.Name = "Rocket";
- rocket.Expiry = new DateTime(2000, 2, 2, 23, 1, 30, DateTimeKind.Utc);
- Product alien = new Product();
- alien.Name = "Alien";
-
- product.Add(rocket);
- product.Add(alien);
- }
- }
-
- public enum StoreColor
- {
- Black,
- Red,
- Yellow,
- White
- }
-
- public class ClassWithGuid
- {
- public Guid GuidField;
- }
-
- public class ClassWithArray
- {
- private readonly IList bar;
- private string foo;
-
- public ClassWithArray()
- {
- bar = new List() { int.MaxValue };
- }
-
- [JsonProperty("foo")]
- public string Foo
- {
- get { return foo; }
- set { foo = value; }
- }
-
- [JsonProperty(PropertyName = "bar")]
- public IList Bar
- {
- get { return bar; }
- }
- }
-
- [JsonObject]
- public class ConverableMembers
- {
- public string String = "string";
- public int Int32 = int.MaxValue;
- public uint UInt32 = uint.MaxValue;
- public byte Byte = byte.MaxValue;
- public sbyte SByte = sbyte.MaxValue;
- public short Short = short.MaxValue;
- public ushort UShort = ushort.MaxValue;
- public long Long = long.MaxValue;
- public ulong ULong = long.MaxValue;
- public double Double = double.MaxValue;
- public float Float = float.MaxValue;
- public DBNull DBNull = DBNull.Value;
- public bool Bool = true;
- public char Char = '\0';
- }
-
- [JsonObject(MemberSerialization.OptIn)]
- public class JsonIgnoreAttributeOnClassTestClass
- {
- private int _property = 21;
- private int _ignoredProperty = 12;
-
- [JsonProperty("TheField")]
- public int Field;
-
- [JsonProperty]
- public int Property
- {
- get { return _property; }
- }
-
- public int IgnoredField;
-
- [JsonProperty]
- [JsonIgnore] // JsonIgnore should take priority
- public int IgnoredProperty
- {
- get { return _ignoredProperty; }
- }
- }
-
- [JsonObject(MemberSerialization.OptIn)]
- public class Person
- {
- // "John Smith"
- [JsonProperty]
- public string Name { get; set; }
-
- // "2000-12-15T22:11:03"
- [JsonProperty]
- //[JsonConverter(typeof(IsoDateTimeConverter))]
- public DateTime BirthDate { get; set; }
-
- // new Date(976918263055)
- [JsonProperty]
- //[JsonConverter(typeof(JavaScriptDateTimeConverter))]
- public DateTime LastModified { get; set; }
-
- // not serialized
- public string Department { get; set; }
- }
-
public class JsonSerializerTest : TestFixtureBase
{
[Test]
@@ -314,13 +141,6 @@ namespace Newtonsoft.Json.Tests
Console.WriteLine(jsonText);
}
- public class MethodExecutorObject
- {
- public string serverClassName;
- public object[] serverMethodParams;
- public string clientGetResultFunction;
- }
-
[Test]
public void TestMethodExecutorObject()
{
@@ -351,12 +171,6 @@ namespace Newtonsoft.Json.Tests
Assert.AreEqual("Orange", p["Name"].ToString());
}
- public class TypedSubHashtable
- {
- public string Name;
- public Hashtable Hash;
- }
-
[Test]
public void TypedHashtableDeserialization()
{
@@ -371,16 +185,6 @@ namespace Newtonsoft.Json.Tests
}
#endif
- public class GetOnlyPropertyClass
- {
- public string Field = "Field";
-
- public string GetOnlyProperty
- {
- get { return "GetOnlyProperty"; }
- }
- }
-
[Test]
public void SerializeDeserializeGetOnlyProperty()
{
@@ -392,16 +196,6 @@ namespace Newtonsoft.Json.Tests
Assert.AreEqual(c.GetOnlyProperty, "GetOnlyProperty");
}
- public class SetOnlyPropertyClass
- {
- public string Field = "Field";
-
- public string SetOnlyProperty
- {
- set { }
- }
- }
-
[Test]
public void SerializeDeserializeSetOnlyProperty()
{
@@ -412,30 +206,6 @@ namespace Newtonsoft.Json.Tests
Assert.AreEqual(c.Field, "Field");
}
- public class JsonIgnoreAttributeTestClass
- {
- private int _property = 21;
- private int _ignoredProperty = 12;
-
- public int Field;
- public int Property
- {
- get { return _property; }
- }
-
- [JsonIgnore]
- public int IgnoredField;
-
- [JsonIgnore]
- public int IgnoredProperty
- {
- get { return _ignoredProperty; }
- }
-
- [JsonIgnore]
- public Product IgnoredObject = new Product();
- }
-
[Test]
public void JsonIgnoreAttributeTest()
{
@@ -594,39 +364,13 @@ keyword such as type of business.""
Assert.AreEqual(test.SweetCakesCount, test2.SweetCakesCount);
}
- public class BadJsonPropertyClass
- {
- [JsonProperty("pie")]
- public string Pie = "Yum";
-
- public string pie = "PieChart!";
- }
-
[Test]
- [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"A member with the name 'pie' already exists on Newtonsoft.Json.Tests.JsonSerializerTest+BadJsonPropertyClass. Use the JsonPropertyAttribute to specify another name.")]
+ [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"A member with the name 'pie' already exists on Newtonsoft.Json.Tests.TestObjects.BadJsonPropertyClass. Use the JsonPropertyAttribute to specify another name.")]
public void BadJsonPropertyClassSerialize()
{
JsonConvert.SerializeObject(new BadJsonPropertyClass());
}
- public class Article
- {
- public string Name;
-
- public Article()
- {
- }
-
- public Article(string name)
- {
- Name = name;
- }
- }
-
- public class ArticleCollection : List
- {
- }
-
[Test]
public void InheritedListSerialize()
{
@@ -657,26 +401,6 @@ keyword such as type of business.""
CollectionAssert.AreEqual(r1, r2);
}
- public class Person
- {
- private Guid _internalId;
- private string _firstName;
-
- [JsonIgnore]
- public Guid InternalId
- {
- get { return _internalId; }
- set { _internalId = value; }
- }
-
- [JsonProperty("first_name")]
- public string FirstName
- {
- get { return _firstName; }
- set { _firstName = value; }
- }
- }
-
[Test]
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Could not find member 'Price' on object of type 'RuntimeType'")]
public void MissingMemberDeserialize()
@@ -1042,28 +766,6 @@ keyword such as type of business.""
}
#endif
- public class Name
- {
- public string personsName;
-
- public List pNumbers = new List();
-
- public Name(string personsName)
- {
- this.personsName = personsName;
- }
- }
-
- public class PhoneNumber
- {
- public string phoneNumber;
-
- public PhoneNumber(string phoneNumber)
- {
- this.phoneNumber = phoneNumber;
- }
- }
-
[Test]
public void SerializeMemberGenericList()
{
@@ -1085,20 +787,6 @@ keyword such as type of business.""
Assert.AreEqual(0, newName.pNumbers.Count);
}
- public class ConstructorCaseSensitivityClass
- {
- public string param1 { get; set; }
- public string Param1 { get; set; }
- public string Param2 { get; set; }
-
- public ConstructorCaseSensitivityClass(string param1, string Param1, string param2)
- {
- this.param1 = param1;
- this.Param1 = Param1;
- this.Param2 = param2;
- }
- }
-
[Test]
public void ConstructorCaseSensitivity()
{
@@ -1113,72 +801,6 @@ keyword such as type of business.""
Assert.AreEqual("Param2", deserialized.Param2);
}
- public class MemberConverterPrecedenceClassConverter : ConverterPrecedenceClassConverter
- {
- public override string ConverterType
- {
- get { return "Member"; }
- }
- }
-
- public class ClassConverterPrecedenceClassConverter : ConverterPrecedenceClassConverter
- {
- public override string ConverterType
- {
- get { return "Class"; }
- }
- }
-
- public class ArgumentConverterPrecedenceClassConverter : ConverterPrecedenceClassConverter
- {
- public override string ConverterType
- {
- get { return "Argument"; }
- }
- }
-
- public abstract class ConverterPrecedenceClassConverter : JsonConverter
- {
- public abstract string ConverterType { get; }
-
- public override void WriteJson(JsonWriter writer, object value)
- {
- ConverterPrecedenceClass c = (ConverterPrecedenceClass)value;
-
- JToken j = new JArray(ConverterType, c.TestValue);
-
- j.WriteTo(writer);
- }
-
- public override object ReadJson(JsonReader reader, Type objectType)
- {
- JToken j = JArray.Load(reader);
-
- string converter = (string)j[0];
- if (converter != ConverterType)
- throw new Exception("Serialize converter {0} and deserialize converter {1} do not match.".FormatWith(CultureInfo.InvariantCulture, converter, ConverterType));
-
- string testValue = (string)j[1];
- return new ConverterPrecedenceClass(testValue);
- }
-
- public override bool CanConvert(Type objectType)
- {
- return (objectType == typeof(ConverterPrecedenceClass));
- }
- }
-
- [JsonConverter(typeof(ClassConverterPrecedenceClassConverter))]
- public class ConverterPrecedenceClass
- {
- public string TestValue { get; set; }
-
- public ConverterPrecedenceClass(string testValue)
- {
- TestValue = testValue;
- }
- }
-
[Test]
public void SerializerShouldUseClassConverter()
{
@@ -1205,13 +827,6 @@ keyword such as type of business.""
Assert.AreEqual("!Test!", c2.TestValue);
}
- public class MemberConverterClass
- {
- public DateTime DefaultConverter { get; set; }
- [JsonConverter(typeof(IsoDateTimeConverter))]
- public DateTime MemberConverter { get; set; }
- }
-
[Test]
public void SerializerShouldUseMemberConverter()
{
@@ -1242,13 +857,6 @@ keyword such as type of business.""
Assert.AreEqual(testDate, m2.MemberConverter);
}
- public class ClassAndMemberConverterClass
- {
- public ConverterPrecedenceClass DefaultConverter { get; set; }
- [JsonConverter(typeof(MemberConverterPrecedenceClassConverter))]
- public ConverterPrecedenceClass MemberConverter { get; set; }
- }
-
[Test]
public void SerializerShouldUseMemberConverterOverClassAndArgumentConverter()
{
@@ -1265,29 +873,14 @@ keyword such as type of business.""
Assert.AreEqual("MemberConverterValue", c2.MemberConverter.TestValue);
}
- [JsonConverter(typeof(IsoDateTimeConverter))]
- public class IncompatibleJsonAttributeClass
- {
- }
-
[Test]
- [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "JsonConverter IsoDateTimeConverter on Newtonsoft.Json.Tests.JsonSerializerTest+IncompatibleJsonAttributeClass is not compatible with member type IncompatibleJsonAttributeClass.")]
+ [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "JsonConverter IsoDateTimeConverter on Newtonsoft.Json.Tests.TestObjects.IncompatibleJsonAttributeClass is not compatible with member type IncompatibleJsonAttributeClass.")]
public void IncompatibleJsonAttributeShouldThrow()
{
IncompatibleJsonAttributeClass c = new IncompatibleJsonAttributeClass();
JsonConvert.SerializeObject(c);
}
- public abstract class AbstractGenericBase
- {
- public abstract TKey Id { get; set; }
- }
-
- public class GenericImpl : AbstractGenericBase
- {
- public override int Id { get; set; }
- }
-
[Test]
public void GenericAbstractProperty()
{
@@ -1295,15 +888,6 @@ keyword such as type of business.""
Assert.AreEqual(@"{""Id"":0}", json);
}
- public class DefaultValueAttributeTestClass
- {
- [DefaultValue("TestProperty1Value")]
- public string TestProperty1 { get; set; }
-
- [DefaultValue(21)]
- public int TestField1;
- }
-
[Test]
public void DefaultValueAttributeTest()
{
@@ -1324,16 +908,6 @@ keyword such as type of business.""
Assert.AreEqual(@"{}", json);
}
- public class Invoice
- {
- public string Company { get; set; }
- public decimal Amount { get; set; }
- [DefaultValue(false)]
- public bool Paid { get; set; }
- [DefaultValue(null)]
- public DateTime? PaidDate { get; set; }
- }
-
[Test]
public void SerializeInvoice()
{
@@ -1369,41 +943,6 @@ keyword such as type of business.""
Assert.AreEqual("1", json);
}
- public class PersonRaw
- {
- private Guid _internalId;
- private string _firstName;
- private string _lastName;
- private JsonRaw _rawContent;
-
- [JsonIgnore]
- public Guid InternalId
- {
- get { return _internalId; }
- set { _internalId = value; }
- }
-
- [JsonProperty("first_name")]
- public string FirstName
- {
- get { return _firstName; }
- set { _firstName = value; }
- }
-
- public JsonRaw RawContent
- {
- get { return _rawContent; }
- set { _rawContent = value; }
- }
-
- [JsonProperty("last_name")]
- public string LastName
- {
- get { return _lastName; }
- set { _lastName = value; }
- }
- }
-
[Test]
public void SerializeJsonRaw()
{
@@ -1432,21 +971,11 @@ keyword such as type of business.""
Assert.AreEqual("LastNameValue", personRaw.LastName);
}
- public class UserNullablle
- {
- public Guid Id;
- public string FName;
- public string LName;
- public int RoleId;
- public int? NullableRoleId;
- public int? NullRoleId;
- public bool? Active;
- }
[Test]
public void DeserializeNullableMember()
{
- UserNullablle userNullablle = new UserNullablle
+ UserNullable userNullablle = new UserNullable
{
Id = new Guid("AD6205E8-0DF4-465d-AEA6-8BA18E93A7E7"),
FName = "FirstValue",
@@ -1461,7 +990,7 @@ keyword such as type of business.""
Assert.AreEqual(@"{""Id"":""ad6205e8-0df4-465d-aea6-8ba18e93a7e7"",""FName"":""FirstValue"",""LName"":""LastValue"",""RoleId"":5,""NullableRoleId"":6,""NullRoleId"":null,""Active"":true}", json);
- UserNullablle userNullablleDeserialized = JsonConvert.DeserializeObject(json);
+ UserNullable userNullablleDeserialized = JsonConvert.DeserializeObject(json);
Assert.AreEqual(new Guid("AD6205E8-0DF4-465d-AEA6-8BA18E93A7E7"), userNullablleDeserialized.Id);
Assert.AreEqual("FirstValue", userNullablleDeserialized.FName);
@@ -1472,13 +1001,6 @@ keyword such as type of business.""
Assert.AreEqual(true, userNullablleDeserialized.Active);
}
- public class MyClass
- {
- public int PreProperty { get; set; }
- //public DateTime DateProperty { get; set; }
- public int PostProperty { get; set; }
- }
-
[Test]
public void MissingMemberIgnoreComplexValue()
{
@@ -1492,5 +1014,63 @@ keyword such as type of business.""
Assert.AreEqual(1, myClass.PreProperty);
Assert.AreEqual(2, myClass.PostProperty);
}
+
+ [Test]
+ public void DeserializeInt64ToNullableDouble()
+ {
+ string json = @"{""Height"":1}";
+
+ DoubleClass c = JsonConvert.DeserializeObject(json);
+ Assert.AreEqual(1, c.Height);
+ }
+
+ [Test]
+ public void SerializeTypeProperty()
+ {
+ TypeClass typeClass = new TypeClass {TypeProperty = typeof (bool)};
+
+ string json = JsonConvert.SerializeObject(typeClass);
+ Assert.AreEqual(@"{""TypeProperty"":""System.Boolean""}", json);
+
+ TypeClass typeClass2 = JsonConvert.DeserializeObject(json);
+ Assert.AreEqual(typeof(bool), typeClass2.TypeProperty);
+ }
+
+ [Test]
+ public void RequiredMembersClass()
+ {
+ RequiredMembersClass c = new RequiredMembersClass()
+ {
+ BirthDate = new DateTime(2000, 12, 20, 10, 55, 55, DateTimeKind.Utc),
+ FirstName = "Bob",
+ LastName = "Smith",
+ MiddleName = "Cosmo"
+ };
+
+ string json = JsonConvert.SerializeObject(c, Formatting.Indented);
+
+ Assert.AreEqual(@"{
+ ""FirstName"": ""Bob"",
+ ""MiddleName"": ""Cosmo"",
+ ""LastName"": ""Smith"",
+ ""BirthDate"": ""\/Date(977309755000)\/""
+}", json);
+
+ RequiredMembersClass c2 = JsonConvert.DeserializeObject(json);
+
+ Assert.AreEqual("Bob", c2.FirstName);
+ Assert.AreEqual(new DateTime(2000, 12, 20, 10, 55, 55, DateTimeKind.Utc), c2.BirthDate);
+ }
+
+ [Test]
+ [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Required property 'LastName' not found in JSON.")]
+ public void RequiredMembersClassMissingRequiredProperty()
+ {
+ string json = @"{
+ ""FirstName"": ""Bob""
+}";
+
+ JsonConvert.DeserializeObject(json);
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs
index d6348eef..da144e71 100644
--- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs
@@ -348,5 +348,81 @@ namespace Newtonsoft.Json.Tests
reader.Read();
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
}
+
+ [Test]
+ public void ReadFloatingPointNumber()
+ {
+ string json =
+ @"[0.0,0.0,0.1,1.0,1.000001,1E-06,4.94065645841247E-324,Infinity,-Infinity,NaN,1.7976931348623157E+308,-1.7976931348623157E+308,Infinity,-Infinity,NaN]";
+
+ using (JsonReader jsonReader = new JsonTextReader(new StringReader(json)))
+ {
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.StartArray, jsonReader.TokenType);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(0.0, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(0.0, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(0.1, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(1.0, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(1.000001, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(1E-06, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(4.94065645841247E-324, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(double.PositiveInfinity, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(double.NegativeInfinity, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(double.NaN, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(double.MaxValue, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(double.MinValue, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(double.PositiveInfinity, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(double.NegativeInfinity, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.Float, jsonReader.TokenType);
+ Assert.AreEqual(double.NaN, jsonReader.Value);
+
+ jsonReader.Read();
+ Assert.AreEqual(JsonToken.EndArray, jsonReader.TokenType);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs
index 24508262..788be268 100644
--- a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs
@@ -410,5 +410,61 @@ namespace Newtonsoft.Json.Tests
Assert.AreEqual(@"{""d0"":[1,2],""d1"":[1,2],""d2"":[1,2]}", sb.ToString());
}
+
+ [Test]
+ public void WriteObjectNestedInConstructor()
+ {
+ StringBuilder sb = new StringBuilder();
+ StringWriter sw = new StringWriter(sb);
+
+ using (JsonWriter jsonWriter = new JsonTextWriter(sw))
+ {
+ jsonWriter.WriteStartObject();
+ jsonWriter.WritePropertyName("con");
+
+ jsonWriter.WriteStartConstructor("Ext.data.JsonStore");
+ jsonWriter.WriteStartObject();
+ jsonWriter.WritePropertyName("aa");
+ jsonWriter.WriteValue("aa");
+ jsonWriter.WriteEndObject();
+ jsonWriter.WriteEndConstructor();
+
+ jsonWriter.WriteEndObject();
+ }
+
+ Assert.AreEqual(@"{""con"":new Ext.data.JsonStore({""aa"":""aa""})}", sb.ToString());
+ }
+
+ [Test]
+ public void WriteFloatingPointNumber()
+ {
+ StringBuilder sb = new StringBuilder();
+ StringWriter sw = new StringWriter(sb);
+
+ using (JsonWriter jsonWriter = new JsonTextWriter(sw))
+ {
+ jsonWriter.WriteStartArray();
+
+ jsonWriter.WriteValue(0.0);
+ jsonWriter.WriteValue(0f);
+ jsonWriter.WriteValue(0.1);
+ jsonWriter.WriteValue(1.0);
+ jsonWriter.WriteValue(1.000001);
+ jsonWriter.WriteValue(0.000001);
+ jsonWriter.WriteValue(double.Epsilon);
+ jsonWriter.WriteValue(double.PositiveInfinity);
+ jsonWriter.WriteValue(double.NegativeInfinity);
+ jsonWriter.WriteValue(double.NaN);
+ jsonWriter.WriteValue(double.MaxValue);
+ jsonWriter.WriteValue(double.MinValue);
+ jsonWriter.WriteValue(float.PositiveInfinity);
+ jsonWriter.WriteValue(float.NegativeInfinity);
+ jsonWriter.WriteValue(float.NaN);
+
+ jsonWriter.WriteEndArray();
+ }
+
+ Assert.AreEqual(@"[0.0,0.0,0.1,1.0,1.000001,1E-06,4.94065645841247E-324,Infinity,-Infinity,NaN,1.7976931348623157E+308,-1.7976931348623157E+308,Infinity,-Infinity,NaN]", sb.ToString());
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/JsonTokenWriterTest.cs b/Src/Newtonsoft.Json.Tests/JsonTokenWriterTest.cs
index cf454339..f6c404a9 100644
--- a/Src/Newtonsoft.Json.Tests/JsonTokenWriterTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonTokenWriterTest.cs
@@ -39,7 +39,7 @@ namespace Newtonsoft.Json.Tests
[Test]
public void ValueFormatting()
{
- JContainer root;
+ JToken root;
using (JsonTokenWriter jsonWriter = new JsonTokenWriter())
{
jsonWriter.WriteStartArray();
diff --git a/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs b/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs
new file mode 100644
index 00000000..c757c352
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/JsonValidatingReaderTests.cs
@@ -0,0 +1,1150 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using System.Xml;
+using System.Xml.Schema;
+using Newtonsoft.Json.Schema;
+
+namespace Newtonsoft.Json.Tests
+{
+ public class JsonValidatingReaderTests : TestFixtureBase
+ {
+ [Test]
+ public void CheckInnerReader()
+ {
+ string json = "{'name':'James','hobbies':['pie','cake']}";
+ JsonReader reader = new JsonTextReader(new StringReader(json));
+
+ JsonValidatingReader validatingReader = new JsonValidatingReader(reader);
+ Assert.AreEqual(reader, validatingReader.Reader);
+ }
+
+ [Test]
+ public void ValidateTypes()
+ {
+ string schemaJson = @"{
+ ""description"":""A person"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""name"":{""type"":""string""},
+ ""hobbies"":
+ {
+ ""type"":""array"",
+ ""items"": {""type"":""string""}
+ }
+ }
+}";
+
+ string json = @"{'name':""James"",'hobbies':[""pie"",'cake']}";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ JsonSchema schema = JsonSchema.Parse(schemaJson);
+ reader.Schema = schema;
+ Assert.AreEqual(schema, reader.Schema);
+
+ Assert.AreEqual(0, reader.Depth);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("name", reader.Value.ToString());
+
+ Assert.AreEqual(1, reader.Depth);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("James", reader.Value.ToString());
+ Assert.AreEqual(typeof(string), reader.ValueType);
+ Assert.AreEqual('"', reader.QuoteChar);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("hobbies", reader.Value.ToString());
+ Assert.AreEqual('\'', reader.QuoteChar);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("pie", reader.Value.ToString());
+ Assert.AreEqual('"', reader.QuoteChar);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("cake", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+
+ Assert.IsNull(validationEventArgs);
+ }
+
+ [Test]
+ public void ValidateUnrestrictedArray()
+ {
+ string schemaJson = @"{
+ ""type"":""array""
+}";
+
+ string json = "['pie','cake',['nested1','nested2'],{'nestedproperty1':1.1,'nestedproperty2':[null]}]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("pie", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("cake", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("nested1", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("nested2", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("nestedproperty1", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Float, reader.TokenType);
+ Assert.AreEqual(1.1, reader.Value);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("nestedproperty2", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Null, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsNull(validationEventArgs);
+ }
+
+ [Test]
+ public void StringLessThanMinimumLength()
+ {
+ string schemaJson = @"{
+ ""type"":""string"",
+ ""minLength"":5,
+ ""maxLength"":50,
+}";
+
+ string json = "'pie'";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("String 'pie' is less than minimum length of 5.", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void StringGreaterThanMaximumLength()
+ {
+ string schemaJson = @"{
+ ""type"":""string"",
+ ""minLength"":5,
+ ""maxLength"":10
+}";
+
+ string json = "'The quick brown fox jumps over the lazy dog.'";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("String 'The quick brown fox jumps over the lazy dog.' exceeds maximum length of 10.", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void StringIsNotInEnum()
+ {
+ string schemaJson = @"{
+ ""type"":""array"",
+ ""items"":{
+ ""type"":""string"",
+ ""enum"":[""one"",""two""]
+ },
+ ""maxItems"":3
+}";
+
+ string json = "['one','two','THREE']";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual(@"Value ""THREE"" is not defined in enum.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void StringDoesNotMatchPattern()
+ {
+ string schemaJson = @"{
+ ""type"":""string"",
+ ""pattern"":""foo""
+}";
+
+ string json = "'The quick brown fox jumps over the lazy dog.'";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("String 'The quick brown fox jumps over the lazy dog.' does not match regex pattern 'foo'.", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void IntegerGreaterThanMaximumValue()
+ {
+ string schemaJson = @"{
+ ""type"":""integer"",
+ ""maximum"":5
+}";
+
+ string json = "10";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Integer, reader.TokenType);
+ Assert.AreEqual("Integer 10 exceeds maximum value of 5.", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ [ExpectedException(typeof(JsonSchemaException), ExpectedMessage = "Integer 10 exceeds maximum value of 5.")]
+ public void ThrowExceptionWhenNoValidationEventHandler()
+ {
+ string schemaJson = @"{
+ ""type"":""integer"",
+ ""maximum"":5
+}";
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader("10")));
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ }
+
+ [Test]
+ public void IntegerLessThanMinimumValue()
+ {
+ string schemaJson = @"{
+ ""type"":""integer"",
+ ""minimum"":5
+}";
+
+ string json = "1";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Integer, reader.TokenType);
+ Assert.AreEqual("Integer 1 is less than minimum value of 5.", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void IntegerIsNotInEnum()
+ {
+ string schemaJson = @"{
+ ""type"":""array"",
+ ""items"":{
+ ""type"":""integer"",
+ ""enum"":[1,2]
+ },
+ ""maxItems"":3
+}";
+
+ string json = "[1,2,3]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Integer, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Integer, reader.TokenType);
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Integer, reader.TokenType);
+ Assert.AreEqual(@"Value 3 is not defined in enum.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void FloatGreaterThanMaximumValue()
+ {
+ string schemaJson = @"{
+ ""type"":""number"",
+ ""maximum"":5
+}";
+
+ string json = "10.0";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Float, reader.TokenType);
+ Assert.AreEqual("Float 10.0 exceeds maximum value of 5.", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void FloatLessThanMinimumValue()
+ {
+ string schemaJson = @"{
+ ""type"":""number"",
+ ""minimum"":5
+}";
+
+ string json = "1.1";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Float, reader.TokenType);
+ Assert.AreEqual("Float 1.1 is less than minimum value of 5.", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void FloatIsNotInEnum()
+ {
+ string schemaJson = @"{
+ ""type"":""array"",
+ ""items"":{
+ ""type"":""number"",
+ ""enum"":[1.1,2.2]
+ },
+ ""maxItems"":3
+}";
+
+ string json = "[1.1,2.2,3.0]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Float, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Float, reader.TokenType);
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Float, reader.TokenType);
+ Assert.AreEqual(@"Value 3.0 is not defined in enum.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void FloatExceedsMaxDecimalPlaces()
+ {
+ string schemaJson = @"{
+ ""type"":""array"",
+ ""items"":{
+ ""type"":""number"",
+ ""maxDecimal"":2
+ }
+}";
+
+ string json = "[1.1,2.2,4.001]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Float, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Float, reader.TokenType);
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Float, reader.TokenType);
+ Assert.AreEqual(@"Float 4.001 exceeds the maximum allowed number decimal places of 2.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void NullNotInEnum()
+ {
+ string schemaJson = @"{
+ ""type"":""array"",
+ ""items"":{
+ ""type"":""null"",
+ ""enum"":[]
+ },
+ ""maxItems"":3
+}";
+
+ string json = "[null]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Null, reader.TokenType);
+ Assert.AreEqual(@"Value null is not defined in enum.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void BooleanNotInEnum()
+ {
+ string schemaJson = @"{
+ ""type"":""array"",
+ ""items"":{
+ ""type"":""boolean"",
+ ""enum"":[true]
+ },
+ ""maxItems"":3
+}";
+
+ string json = "[true,false]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Boolean, reader.TokenType);
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Boolean, reader.TokenType);
+ Assert.AreEqual(@"Value false is not defined in enum.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void ArrayCountGreaterThanMaximumItems()
+ {
+ string schemaJson = @"{
+ ""type"":""array"",
+ ""minItems"":2,
+ ""maxItems"":3
+}";
+
+ string json = "[null,null,null,null]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Null, reader.TokenType);
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Null, reader.TokenType);
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Null, reader.TokenType);
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Null, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+ Assert.AreEqual("Array item count 4 exceeds maximum count of 3.", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void ArrayCountLessThanMinimumItems()
+ {
+ string schemaJson = @"{
+ ""type"":""array"",
+ ""minItems"":2,
+ ""maxItems"":3
+}";
+
+ string json = "[null]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Null, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+ Assert.AreEqual("Array item count 1 is less than minimum count of 2.", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void InvalidDataType()
+ {
+ string schemaJson = @"{
+ ""type"":""string"",
+ ""minItems"":2,
+ ""maxItems"":3,
+ ""items"":{}
+}";
+
+ string json = "[null,null,null,null]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+ Assert.AreEqual(@"Invalid type. Expected String but got Array.", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void StringDisallowed()
+ {
+ string schemaJson = @"{
+ ""type"":""array"",
+ ""items"":{
+ ""disallow"":[""number""]
+ },
+ ""maxItems"":3
+}";
+
+ string json = "['pie',1.1]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Float, reader.TokenType);
+ Assert.AreEqual(@"Type Float is disallowed.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void MissingNonoptionalProperties()
+ {
+ string schemaJson = @"{
+ ""description"":""A person"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""name"":{""type"":""string""},
+ ""hobbies"":{""type"":""string""},
+ ""age"":{""type"":""integer""}
+ }
+}";
+
+ string json = "{'name':'James'}";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("name", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("James", reader.Value.ToString());
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+ Assert.AreEqual("Non-optional properties are missing from object: hobbies, age", validationEventArgs.Message);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void MissingOptionalProperties()
+ {
+ string schemaJson = @"{
+ ""description"":""A person"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""name"":{""type"":""string""},
+ ""hobbies"":{""type"":""string"",optional:true},
+ ""age"":{""type"":""integer"",optional:true}
+ }
+}";
+
+ string json = "{'name':'James'}";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("name", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("James", reader.Value.ToString());
+ Assert.IsNull(validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+
+ Assert.IsNull(validationEventArgs);
+ }
+
+ [Test]
+ public void DisableAdditionalProperties()
+ {
+ string schemaJson = @"{
+ ""description"":""A person"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""name"":{""type"":""string""}
+ },
+ ""additionalProperties"":false
+}";
+
+ string json = "{'name':'James','additionalProperty1':null,'additionalProperty2':null}";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("name", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("James", reader.Value.ToString());
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("additionalProperty1", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Null, reader.TokenType);
+ Assert.AreEqual(null, reader.Value);
+ Assert.AreEqual("Property 'additionalProperty1' has not been defined and schema does not allow additional properties.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("additionalProperty2", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Null, reader.TokenType);
+ Assert.AreEqual(null, reader.Value);
+ Assert.AreEqual("Property 'additionalProperty2' has not been defined and schema does not allow additional properties.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ [Test]
+ public void ExtendsStringGreaterThanMaximumLength()
+ {
+ string schemaJson = @"{
+ ""extends"":{
+ ""type"":""string"",
+ ""minLength"":5,
+ ""maxLength"":10
+ },
+ ""maxLength"":9
+}";
+
+ List errors = new List();
+ string json = "'The quick brown fox jumps over the lazy dog.'";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; errors.Add(validationEventArgs.Message); };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual(1, errors.Count);
+ Assert.AreEqual("String 'The quick brown fox jumps over the lazy dog.' exceeds maximum length of 9.", errors[0]);
+
+ Assert.IsNotNull(validationEventArgs);
+ }
+
+ private JsonSchema GetExtendedSchema()
+ {
+ string first = @"{
+ ""id"":""first"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""firstproperty"":{""type"":""string""}
+ },
+ ""additionalProperties"":{}
+}";
+
+ string second = @"{
+ ""id"":""second"",
+ ""type"":""object"",
+ ""extends"":{""$ref"":""first""},
+ ""properties"":
+ {
+ ""secondproperty"":{""type"":""string""}
+ },
+ ""additionalProperties"":false
+}";
+
+ JsonSchemaResolver resolver = new JsonSchemaResolver();
+ JsonSchema firstSchema = JsonSchema.Parse(first, resolver);
+ JsonSchema secondSchema = JsonSchema.Parse(second, resolver);
+
+ return secondSchema;
+ }
+
+ [Test]
+ public void ExtendsDisallowAdditionProperties()
+ {
+ string json = "{'firstproperty':'blah','secondproperty':'blah2','additional':'blah3','additional2':'blah4'}";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = GetExtendedSchema();
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("firstproperty", reader.Value.ToString());
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("blah", reader.Value.ToString());
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("secondproperty", reader.Value.ToString());
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("blah2", reader.Value.ToString());
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("additional", reader.Value.ToString());
+ Assert.AreEqual("Property 'additional' has not been defined and schema does not allow additional properties.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("blah3", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("additional2", reader.Value.ToString());
+ Assert.AreEqual("Property 'additional2' has not been defined and schema does not allow additional properties.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("blah4", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+
+ Assert.IsFalse(reader.Read());
+ }
+
+ [Test]
+ public void ExtendsMissingNonoptionalProperties()
+ {
+ string json = "{}";
+
+ List errors = new List();
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { errors.Add(args.Message); };
+ reader.Schema = GetExtendedSchema();
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+
+ Assert.AreEqual(1, errors.Count);
+ Assert.AreEqual("Non-optional properties are missing from object: secondproperty, firstproperty", errors[0]);
+ }
+
+ [Test]
+ public void sdfsdf()
+ {
+ string schemaJson = @"{
+ ""type"":""array"",
+ ""items"": [{""type"":""string""},{""type"":""integer""}],
+ ""additionalProperties"": false
+}";
+
+ string json = @"[1, 'a', null]";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; };
+ reader.Schema = JsonSchema.Parse(schemaJson);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Integer, reader.TokenType);
+ Assert.AreEqual("Invalid type. Expected String but got Integer.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("Invalid type. Expected Integer but got String.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.Null, reader.TokenType);
+ Assert.AreEqual("Index 3 has not been defined and schema does not allow additional items.", validationEventArgs.Message);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
+
+ Assert.IsFalse(reader.Read());
+ }
+
+ [Test]
+ public void ExtendedComplex()
+ {
+ string first = @"{
+ ""id"":""first"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""firstproperty"":{""type"":""string""},
+ ""secondproperty"":{""type"":""string"",""maxLength"":10},
+ ""thirdproperty"":{
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""thirdproperty_firstproperty"":{""type"":""string"",""maxLength"":10,""minLength"":7}
+ }
+ }
+ },
+ ""additionalProperties"":{}
+}";
+
+ string second = @"{
+ ""id"":""second"",
+ ""type"":""object"",
+ ""extends"":{""$ref"":""first""},
+ ""properties"":
+ {
+ ""secondproperty"":{""type"":""any""},
+ ""thirdproperty"":{
+ ""extends"":{
+ ""properties"":
+ {
+ ""thirdproperty_firstproperty"":{""maxLength"":9,""minLength"":6,""pattern"":""hi2u""}
+ },
+ ""additionalProperties"":{""maxLength"":9,""minLength"":6,""enum"":[""one"",""two""]}
+ },
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""thirdproperty_firstproperty"":{""pattern"":""hi""}
+ },
+ ""additionalProperties"":{""type"":""string"",""enum"":[""two"",""three""]}
+ },
+ ""fourthproperty"":{""type"":""string""}
+ },
+ ""additionalProperties"":false
+}";
+
+ JsonSchemaResolver resolver = new JsonSchemaResolver();
+ JsonSchema firstSchema = JsonSchema.Parse(first, resolver);
+ JsonSchema secondSchema = JsonSchema.Parse(second, resolver);
+
+ JsonSchemaModelBuilder modelBuilder = new JsonSchemaModelBuilder();
+
+ string json = @"{
+ 'firstproperty':'blahblahblahblahblahblah',
+ 'secondproperty':'secasecasecasecaseca',
+ 'thirdproperty':{
+ 'thirdproperty_firstproperty':'aaa',
+ 'additional':'three'
+ }
+}";
+
+ Json.Schema.ValidationEventArgs validationEventArgs = null;
+ List errors = new List();
+
+ JsonValidatingReader reader = new JsonValidatingReader(new JsonTextReader(new StringReader(json)));
+ reader.ValidationEventHandler += (sender, args) => { validationEventArgs = args; errors.Add(validationEventArgs.Message); };
+ reader.Schema = secondSchema;
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("firstproperty", reader.Value.ToString());
+ Assert.AreEqual(null, validationEventArgs);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("blahblahblahblahblahblah", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("secondproperty", reader.Value.ToString());
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("secasecasecasecaseca", reader.Value.ToString());
+ Assert.AreEqual(1, errors.Count);
+ Assert.AreEqual("String 'secasecasecasecaseca' exceeds maximum length of 10.", errors[0]);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("thirdproperty", reader.Value.ToString());
+ Assert.AreEqual(1, errors.Count);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+ Assert.AreEqual(1, errors.Count);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("thirdproperty_firstproperty", reader.Value.ToString());
+ Assert.AreEqual(1, errors.Count);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("aaa", reader.Value.ToString());
+ Assert.AreEqual(4, errors.Count);
+ Assert.AreEqual("String 'aaa' is less than minimum length of 7.", errors[1]);
+ Assert.AreEqual("String 'aaa' does not match regex pattern 'hi'.", errors[2]);
+ Assert.AreEqual("String 'aaa' does not match regex pattern 'hi2u'.", errors[3]);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
+ Assert.AreEqual("additional", reader.Value.ToString());
+ Assert.AreEqual(4, errors.Count);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.String, reader.TokenType);
+ Assert.AreEqual("three", reader.Value.ToString());
+ Assert.AreEqual(5, errors.Count);
+ Assert.AreEqual("String 'three' is less than minimum length of 6.", errors[4]);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+
+ Assert.IsFalse(reader.Read());
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Linq/JConstructorTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JConstructorTests.cs
new file mode 100644
index 00000000..353691d0
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Linq/JConstructorTests.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Linq;
+using NUnit.Framework;
+using System.IO;
+
+namespace Newtonsoft.Json.Tests.Linq
+{
+ public class JConstructorTests : TestFixtureBase
+ {
+ [Test]
+ public void Load()
+ {
+ JsonReader reader = new JsonTextReader(new StringReader("new Date(123)"));
+ reader.Read();
+
+ JConstructor constructor = JConstructor.Load(reader);
+ Assert.AreEqual("Date", constructor.Name);
+ Assert.IsTrue(JToken.DeepEquals(new JValue(123), constructor.Values().ElementAt(0)));
+ }
+
+ [Test]
+ public void CreateWithMultiValue()
+ {
+ JConstructor constructor = new JConstructor("Test", new List { 1, 2, 3 });
+ Assert.AreEqual("Test", constructor.Name);
+ Assert.AreEqual(3, constructor.Children().Count());
+ Assert.AreEqual(1, (int)constructor.Children().ElementAt(0));
+ Assert.AreEqual(2, (int)constructor.Children().ElementAt(1));
+ Assert.AreEqual(3, (int)constructor.Children().ElementAt(2));
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs
index 9323a27d..af5303ac 100644
--- a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using Newtonsoft.Json.Tests.TestObjects;
using NUnit.Framework;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
@@ -235,7 +236,7 @@ Parameter name: arrayIndex")]
[Test]
public void FromObjectRaw()
{
- JsonSerializerTest.PersonRaw raw = new JsonSerializerTest.PersonRaw
+ PersonRaw raw = new PersonRaw
{
FirstName = "FirstNameValue",
RawContent = new JsonRaw("[1,2,3,4,5]"),
@@ -253,7 +254,7 @@ Parameter name: arrayIndex")]
[Test]
public void JsonTokenReader()
{
- JsonSerializerTest.PersonRaw raw = new JsonSerializerTest.PersonRaw
+ PersonRaw raw = new PersonRaw
{
FirstName = "FirstNameValue",
RawContent = new JsonRaw("[1,2,3,4,5]"),
@@ -294,7 +295,7 @@ Parameter name: arrayIndex")]
[Test]
public void DeserializeFromRaw()
{
- JsonSerializerTest.PersonRaw raw = new JsonSerializerTest.PersonRaw
+ PersonRaw raw = new PersonRaw
{
FirstName = "FirstNameValue",
RawContent = new JsonRaw("[1,2,3,4,5]"),
@@ -305,7 +306,7 @@ Parameter name: arrayIndex")]
JsonReader reader = new JsonTokenReader(o);
JsonSerializer serializer = new JsonSerializer();
- raw = (JsonSerializerTest.PersonRaw)serializer.Deserialize(reader, typeof(JsonSerializerTest.PersonRaw));
+ raw = (PersonRaw)serializer.Deserialize(reader, typeof(PersonRaw));
Assert.AreEqual("FirstNameValue", raw.FirstName);
Assert.AreEqual("LastNameValue", raw.LastName);
diff --git a/Src/Newtonsoft.Json.Tests/Linq/JPropertyTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JPropertyTests.cs
new file mode 100644
index 00000000..a8b1ed85
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Linq/JPropertyTests.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Linq;
+using NUnit.Framework;
+using System.IO;
+
+namespace Newtonsoft.Json.Tests.Linq
+{
+ public class JPropertyTests : TestFixtureBase
+ {
+ [Test]
+ public void Load()
+ {
+ JsonReader reader = new JsonTextReader(new StringReader("{'propertyname':['value1']}"));
+ reader.Read();
+
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+ reader.Read();
+
+ JProperty property = JProperty.Load(reader);
+ Assert.AreEqual("propertyname", property.Name);
+ Assert.IsTrue(JToken.DeepEquals(JArray.Parse("['value1']"), property.Value));
+
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+
+ reader = new JsonTextReader(new StringReader("{'propertyname':null}"));
+ reader.Read();
+
+ Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
+ reader.Read();
+
+ property = JProperty.Load(reader);
+ Assert.AreEqual("propertyname", property.Name);
+ Assert.IsTrue(JToken.DeepEquals(new JValue(null, JsonTokenType.Null), property.Value));
+
+ Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
+ }
+
+ [Test]
+ public void MultiContentConstructor()
+ {
+ JProperty p = new JProperty("error", new List { "one", "two" });
+ JArray a = (JArray) p.Value;
+
+ Assert.AreEqual(a.Count, 2);
+ Assert.AreEqual("one", (string)a[0]);
+ Assert.AreEqual("two", (string)a[1]);
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs
index d35b5f5a..ecf8e0b9 100644
--- a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs
@@ -29,11 +29,47 @@ using System.Linq;
using System.Text;
using NUnit.Framework;
using Newtonsoft.Json.Linq;
+using System.IO;
namespace Newtonsoft.Json.Tests.Linq
{
public class JTokenTests : TestFixtureBase
{
+ [Test]
+ public void ReadFrom()
+ {
+ JObject o = (JObject)JToken.ReadFrom(new JsonTextReader(new StringReader("{'pie':true}")));
+ Assert.AreEqual(true, (bool)o["pie"]);
+
+ JArray a = (JArray)JToken.ReadFrom(new JsonTextReader(new StringReader("[1,2,3]")));
+ Assert.AreEqual(1, (int)a[0]);
+ Assert.AreEqual(2, (int)a[1]);
+ Assert.AreEqual(3, (int)a[2]);
+
+ JsonReader reader = new JsonTextReader(new StringReader("{'pie':true}"));
+ reader.Read();
+ reader.Read();
+
+ JProperty p = (JProperty)JToken.ReadFrom(reader);
+ Assert.AreEqual("pie", p.Name);
+ Assert.AreEqual(true, (bool)p.Value);
+
+ JConstructor c = (JConstructor)JToken.ReadFrom(new JsonTextReader(new StringReader("new Date(1)")));
+ Assert.AreEqual("Date", c.Name);
+ Assert.IsTrue(JToken.DeepEquals(new JValue(1), c.Values().ElementAt(0)));
+
+ JValue v;
+
+ v = (JValue)JToken.ReadFrom(new JsonTextReader(new StringReader(@"""stringvalue""")));
+ Assert.AreEqual("stringvalue", (string)v);
+
+ v = (JValue)JToken.ReadFrom(new JsonTextReader(new StringReader(@"1")));
+ Assert.AreEqual(1, (int)v);
+
+ v = (JValue)JToken.ReadFrom(new JsonTextReader(new StringReader(@"1.1")));
+ Assert.AreEqual(1.1, (double)v);
+ }
+
[Test]
public void Parent()
{
diff --git a/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs b/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs
index 8b52a5fe..82740cfb 100644
--- a/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs
+++ b/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs
@@ -32,6 +32,7 @@ using Newtonsoft.Json.Linq;
using System.Xml;
using System.IO;
using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Tests.TestObjects;
namespace Newtonsoft.Json.Tests.Linq
{
@@ -351,13 +352,13 @@ keyword such as type of business.""
[
""1"",
2,
- 3,
+ 3.0,
""\/Date(-62030076711000)\/""
],
new ConstructorName(
""param1"",
2,
- 3
+ 3.0
)
]", a.ToString());
}
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj
index 2fe5a847..009dff6d 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj
@@ -58,12 +58,59 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -75,11 +122,14 @@
-
+
+
+
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj
index 0ab0c069..f5202b28 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj
@@ -63,12 +63,59 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -80,11 +127,14 @@
-
+
+
+
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
index 6ff2c78d..602c090a 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
@@ -76,9 +76,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -98,6 +145,9 @@
+
+
+
diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
index 83d36690..fdc76e27 100644
--- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
+++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
@@ -20,7 +20,7 @@ namespace Newtonsoft.Json.Tests
///
public class PerformanceTests : TestFixtureBase
{
- private int Iterations = 5000;
+ private int Iterations = 100;
public enum SerializeMethod
{
diff --git a/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs b/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs
new file mode 100644
index 00000000..bad8accd
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs
@@ -0,0 +1,84 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Newtonsoft.Json.Schema;
+using Newtonsoft.Json.Linq;
+
+namespace Newtonsoft.Json.Tests.Schema
+{
+ public class ExtensionsTests : TestFixtureBase
+ {
+ [Test]
+ public void IsValid()
+ {
+ JsonSchema schema = JsonSchema.Parse("{'type':'integer'}");
+ JToken stringToken = JToken.FromObject("pie");
+ JToken integerToken = JToken.FromObject(1);
+
+ Assert.AreEqual(false, stringToken.IsValid(schema));
+ Assert.AreEqual(true, integerToken.IsValid(schema));
+ }
+
+ [Test]
+ public void ValidateWithEventHandler()
+ {
+ JsonSchema schema = JsonSchema.Parse("{'pattern':'lol'}");
+ JToken stringToken = JToken.FromObject("pie lol");
+
+ List errors = new List();
+ stringToken.Validate(schema, (sender, args) => errors.Add(args.Message));
+ Assert.AreEqual(0, errors.Count);
+
+ stringToken = JToken.FromObject("pie");
+
+ stringToken.Validate(schema, (sender, args) => errors.Add(args.Message));
+ Assert.AreEqual(1, errors.Count);
+
+ Assert.AreEqual("String 'pie' does not match regex pattern 'lol'.", errors[0]);
+ }
+
+ [Test]
+ [ExpectedException(typeof(JsonSchemaException), ExpectedMessage = @"String 'pie' does not match regex pattern 'lol'.")]
+ public void ValidateWithOutEventHandlerFailure()
+ {
+ JsonSchema schema = JsonSchema.Parse("{'pattern':'lol'}");
+ JToken stringToken = JToken.FromObject("pie");
+ stringToken.Validate(schema);
+ }
+
+ [Test]
+ public void ValidateWithOutEventHandlerSuccess()
+ {
+ JsonSchema schema = JsonSchema.Parse("{'pattern':'lol'}");
+ JToken stringToken = JToken.FromObject("pie lol");
+ stringToken.Validate(schema);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaBuilderTests.cs b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaBuilderTests.cs
new file mode 100644
index 00000000..43f912e3
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaBuilderTests.cs
@@ -0,0 +1,436 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Newtonsoft.Json.Schema;
+using System.IO;
+using Newtonsoft.Json.Linq;
+
+namespace Newtonsoft.Json.Tests.Schema
+{
+ public class JsonSchemaBuilderTests : TestFixtureBase
+ {
+ [Test]
+ public void Simple()
+ {
+ string json = @"{
+ ""description"":""A person"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""name"":{""type"":""string""},
+ ""hobbies"":
+ {
+ ""type"":""array"",
+ ""items"": {""type"":""string""}
+ }
+ }
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("A person", schema.Description);
+ Assert.AreEqual(JsonSchemaType.Object, schema.Type);
+
+ Assert.AreEqual(2, schema.Properties.Count);
+
+ Assert.AreEqual(JsonSchemaType.String, schema.Properties["name"].Type);
+ Assert.AreEqual(JsonSchemaType.Array, schema.Properties["hobbies"].Type);
+ Assert.AreEqual(JsonSchemaType.String, schema.Properties["hobbies"].Items[0].Type);
+ }
+
+ [Test]
+ public void MultipleTypes()
+ {
+ string json = @"{
+ ""description"":""Age"",
+ ""type"":[""string"", ""integer""]
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Age", schema.Description);
+ Assert.AreEqual(JsonSchemaType.String | JsonSchemaType.Integer, schema.Type);
+ }
+
+ [Test]
+ public void MultipleItems()
+ {
+ string json = @"{
+ ""description"":""MultipleItems"",
+ ""type"":""array"",
+ ""items"": [{""type"":""string""},{""type"":""array""}]
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("MultipleItems", schema.Description);
+ Assert.AreEqual(JsonSchemaType.String, schema.Items[0].Type);
+ Assert.AreEqual(JsonSchemaType.Array, schema.Items[1].Type);
+ }
+
+ [Test]
+ public void AdditionalProperties()
+ {
+ string json = @"{
+ ""description"":""AdditionalProperties"",
+ ""type"":[""string"", ""integer""],
+ ""additionalProperties"":{""type"":[""object"", ""boolean""]}
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("AdditionalProperties", schema.Description);
+ Assert.AreEqual(JsonSchemaType.Object | JsonSchemaType.Boolean, schema.AdditionalProperties.Type);
+ }
+
+ [Test]
+ public void Optional()
+ {
+ string json = @"{
+ ""description"":""Optional"",
+ ""optional"":true
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Optional", schema.Description);
+ Assert.AreEqual(true, schema.Optional);
+ }
+
+ [Test]
+ public void ReadOnly()
+ {
+ string json = @"{
+ ""description"":""ReadOnly"",
+ ""readonly"":true
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("ReadOnly", schema.Description);
+ Assert.AreEqual(true, schema.ReadOnly);
+ }
+
+ [Test]
+ public void Hidden()
+ {
+ string json = @"{
+ ""description"":""Hidden"",
+ ""hidden"":true
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Hidden", schema.Description);
+ Assert.AreEqual(true, schema.Hidden);
+ }
+
+ [Test]
+ public void Id()
+ {
+ string json = @"{
+ ""description"":""Id"",
+ ""id"":""testid""
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Id", schema.Description);
+ Assert.AreEqual("testid", schema.Id);
+ }
+
+ [Test]
+ public void Title()
+ {
+ string json = @"{
+ ""description"":""Title"",
+ ""title"":""testtitle""
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Title", schema.Description);
+ Assert.AreEqual("testtitle", schema.Title);
+ }
+
+ [Test]
+ public void Pattern()
+ {
+ string json = @"{
+ ""description"":""Pattern"",
+ ""pattern"":""testpattern""
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Pattern", schema.Description);
+ Assert.AreEqual("testpattern", schema.Pattern);
+ }
+
+ [Test]
+ public void Format()
+ {
+ string json = @"{
+ ""description"":""Format"",
+ ""format"":""testformat""
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Format", schema.Description);
+ Assert.AreEqual("testformat", schema.Format);
+ }
+
+ [Test]
+ public void Requires()
+ {
+ string json = @"{
+ ""description"":""Requires"",
+ ""requires"":""PurpleMonkeyDishwasher""
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Requires", schema.Description);
+ Assert.AreEqual("PurpleMonkeyDishwasher", schema.Requires);
+ }
+
+ [Test]
+ public void IdentitySingle()
+ {
+ string json = @"{
+ ""description"":""Identity"",
+ ""identity"":""PurpleMonkeyDishwasher""
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Identity", schema.Description);
+ Assert.AreEqual(1, schema.Identity.Count);
+ Assert.AreEqual("PurpleMonkeyDishwasher", schema.Identity[0]);
+ }
+
+ [Test]
+ public void IdentityMultiple()
+ {
+ string json = @"{
+ ""description"":""Identity"",
+ ""identity"":[""PurpleMonkeyDishwasher"",""Antelope""]
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Identity", schema.Description);
+ Assert.AreEqual(2, schema.Identity.Count);
+ Assert.AreEqual("PurpleMonkeyDishwasher", schema.Identity[0]);
+ Assert.AreEqual("Antelope", schema.Identity[1]);
+ }
+
+ [Test]
+ public void MinimumMaximum()
+ {
+ string json = @"{
+ ""description"":""MinimumMaximum"",
+ ""minimum"":1.1,
+ ""maximum"":1.2,
+ ""minItems"":1,
+ ""maxItems"":2,
+ ""minLength"":5,
+ ""maxLength"":50,
+ ""maxDecimal"":3,
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("MinimumMaximum", schema.Description);
+ Assert.AreEqual(1.1, schema.Minimum);
+ Assert.AreEqual(1.2, schema.Maximum);
+ Assert.AreEqual(1, schema.MinimumItems);
+ Assert.AreEqual(2, schema.MaximumItems);
+ Assert.AreEqual(5, schema.MinimumLength);
+ Assert.AreEqual(50, schema.MaximumLength);
+ Assert.AreEqual(3, schema.MaximumDecimals);
+ }
+
+ [Test]
+ public void DisallowSingleType()
+ {
+ string json = @"{
+ ""description"":""DisallowSingleType"",
+ ""disallow"":""string""
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("DisallowSingleType", schema.Description);
+ Assert.AreEqual(JsonSchemaType.String, schema.Disallow);
+ }
+
+ [Test]
+ public void DisallowMultipleTypes()
+ {
+ string json = @"{
+ ""description"":""DisallowMultipleTypes"",
+ ""disallow"":[""string"",""number""]
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("DisallowMultipleTypes", schema.Description);
+ Assert.AreEqual(JsonSchemaType.String | JsonSchemaType.Float, schema.Disallow);
+ }
+
+ [Test]
+ public void DefaultPrimitiveType()
+ {
+ string json = @"{
+ ""description"":""DefaultPrimitiveType"",
+ ""default"":1.1
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("DefaultPrimitiveType", schema.Description);
+ Assert.AreEqual(1.1, (double)schema.Default);
+ }
+
+ [Test]
+ public void DefaultComplexType()
+ {
+ string json = @"{
+ ""description"":""DefaultComplexType"",
+ ""default"":{""pie"":true}
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("DefaultComplexType", schema.Description);
+ Assert.IsTrue(JToken.DeepEquals(JObject.Parse(@"{""pie"":true}"), schema.Default));
+ }
+
+ [Test]
+ public void Options()
+ {
+ string json = @"{
+ ""description"":""NZ Island"",
+ ""type"":""string"",
+ ""options"":
+ [
+ {""value"":""NI"",""label"":""North Island""},
+ {""value"":""SI"",""label"":""South Island""}
+ ]
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("NZ Island", schema.Description);
+ Assert.AreEqual(JsonSchemaType.String, schema.Type);
+
+ Assert.AreEqual(2, schema.Options.Count);
+ Assert.AreEqual("North Island", schema.Options[new JValue("NI")]);
+ Assert.AreEqual("South Island", schema.Options[new JValue("SI")]);
+ }
+
+ [Test]
+ public void Enum()
+ {
+ string json = @"{
+ ""description"":""Type"",
+ ""type"":[""string"",""array""],
+ ""enum"":[""string"",""object"",""array"",""boolean"",""number"",""integer"",""null"",""any""]
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("Type", schema.Description);
+ Assert.AreEqual(JsonSchemaType.String | JsonSchemaType.Array, schema.Type);
+
+ Assert.AreEqual(8, schema.Enum.Count);
+ Assert.AreEqual("string", (string)schema.Enum[0]);
+ Assert.AreEqual("any", (string)schema.Enum[schema.Enum.Count - 1]);
+ }
+
+ [Test]
+ public void CircularReference()
+ {
+ string json = @"{
+ ""id"":""CircularReferenceArray"",
+ ""description"":""CircularReference"",
+ ""type"":[""array""],
+ ""items"":{""$ref"":""CircularReferenceArray""}
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+
+ Assert.AreEqual("CircularReference", schema.Description);
+ Assert.AreEqual("CircularReferenceArray", schema.Id);
+ Assert.AreEqual(JsonSchemaType.Array, schema.Type);
+
+ Assert.AreEqual(schema, schema.Items[0]);
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception), ExpectedMessage = @"Could not resolve schema reference for Id 'MyUnresolvedReference'.")]
+ public void UnresolvedReference()
+ {
+ string json = @"{
+ ""id"":""CircularReferenceArray"",
+ ""description"":""CircularReference"",
+ ""type"":[""array""],
+ ""items"":{""$ref"":""MyUnresolvedReference""}
+}";
+
+ JsonSchemaBuilder builder = new JsonSchemaBuilder(new JsonSchemaResolver());
+ JsonSchema schema = builder.Parse(new JsonTextReader(new StringReader(json)));
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs
new file mode 100644
index 00000000..7b34c5fd
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs
@@ -0,0 +1,265 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Newtonsoft.Json.Tests.TestObjects;
+using NUnit.Framework;
+using Newtonsoft.Json.Schema;
+
+namespace Newtonsoft.Json.Tests.Schema
+{
+ public class JsonSchemaGeneratorTests : TestFixtureBase
+ {
+ [Test]
+ public void Generate_GenericDictionary()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+ JsonSchema schema = generator.Generate(typeof (Dictionary>));
+
+ string json = schema.ToString();
+
+ Assert.AreEqual(@"{
+ ""type"": ""object"",
+ ""additionalProperties"": {
+ ""type"": ""array"",
+ ""items"": {
+ ""type"": ""string""
+ }
+ }
+}", json);
+ }
+
+#if !PocketPC
+ [Test]
+ public void Generate_DefaultValueAttributeTestClass()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+ JsonSchema schema = generator.Generate(typeof(DefaultValueAttributeTestClass));
+
+ string json = schema.ToString();
+
+ Assert.AreEqual(@"{
+ ""description"": ""DefaultValueAttributeTestClass description!"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""TestField1"": {
+ ""type"": ""integer"",
+ ""default"": 21
+ },
+ ""TestProperty1"": {
+ ""type"": [
+ ""string"",
+ ""null""
+ ],
+ ""default"": ""TestProperty1Value""
+ }
+ }
+}", json);
+ }
+#endif
+
+ [Test]
+ public void Generate_Person()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+ JsonSchema schema = generator.Generate(typeof(Person));
+
+ string json = schema.ToString();
+
+ Assert.AreEqual(@"{
+ ""id"": ""Person"",
+ ""title"": ""Title!"",
+ ""description"": ""JsonObjectAttribute description!"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""Name"": {
+ ""type"": [
+ ""string"",
+ ""null""
+ ]
+ },
+ ""BirthDate"": {
+ ""type"": ""string""
+ },
+ ""LastModified"": {
+ ""type"": ""string""
+ }
+ }
+}", json);
+ }
+
+ [Test]
+ public void Generate_UserNullable()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+ JsonSchema schema = generator.Generate(typeof(UserNullable));
+
+ string json = schema.ToString();
+
+ Assert.AreEqual(@"{
+ ""type"": ""object"",
+ ""properties"": {
+ ""Id"": {
+ ""type"": ""string""
+ },
+ ""FName"": {
+ ""type"": [
+ ""string"",
+ ""null""
+ ]
+ },
+ ""LName"": {
+ ""type"": [
+ ""string"",
+ ""null""
+ ]
+ },
+ ""RoleId"": {
+ ""type"": ""integer""
+ },
+ ""NullableRoleId"": {
+ ""type"": [
+ ""integer"",
+ ""null""
+ ]
+ },
+ ""NullRoleId"": {
+ ""type"": [
+ ""integer"",
+ ""null""
+ ]
+ },
+ ""Active"": {
+ ""type"": [
+ ""boolean"",
+ ""null""
+ ]
+ }
+ }
+}", json);
+ }
+
+ [Test]
+ public void Generate_RequiredMembersClass()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+ JsonSchema schema = generator.Generate(typeof(RequiredMembersClass));
+
+ Assert.AreEqual(JsonSchemaType.String, schema.Properties["FirstName"].Type);
+ Assert.AreEqual(JsonSchemaType.String | JsonSchemaType.Null, schema.Properties["MiddleName"].Type);
+ Assert.AreEqual(JsonSchemaType.String, schema.Properties["LastName"].Type);
+ Assert.AreEqual(JsonSchemaType.String, schema.Properties["BirthDate"].Type);
+ }
+
+ [Test]
+ public void Generate_Store()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+ JsonSchema schema = generator.Generate(typeof(Store));
+
+ Assert.AreEqual(11, schema.Properties.Count);
+
+ JsonSchema productArraySchema = schema.Properties["product"];
+ JsonSchema productSchema = productArraySchema.Items[0];
+
+ Assert.AreEqual(4, productSchema.Properties.Count);
+ }
+
+ [Test]
+ public void MissingSchemaIdHandlingTest()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+
+ JsonSchema schema = generator.Generate(typeof(Store));
+ Assert.AreEqual(null, schema.Id);
+
+ generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName;
+ schema = generator.Generate(typeof (Store));
+ Assert.AreEqual(typeof(Store).FullName, schema.Id);
+
+ generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseAssemblyQualifiedName;
+ schema = generator.Generate(typeof(Store));
+ Assert.AreEqual(typeof(Store).AssemblyQualifiedName, schema.Id);
+ }
+
+ [Test]
+ public void Generate_NumberFormatInfo()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+ JsonSchema schema = generator.Generate(typeof(NumberFormatInfo));
+
+ string json = schema.ToString();
+
+ Console.WriteLine(json);
+
+ // Assert.AreEqual(@"{
+ // ""type"": ""object"",
+ // ""additionalProperties"": {
+ // ""type"": ""array"",
+ // ""items"": {
+ // ""type"": ""string""
+ // }
+ // }
+ //}", json);
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception), ExpectedMessage = @"Unresolved circular reference for type 'Newtonsoft.Json.Tests.TestObjects.CircularReferenceClass'. Explicitly define an Id for the type using a JsonObject/JsonArray attribute or automatically generate a type Id using the UndefinedSchemaIdHandling property.")]
+ public void CircularReferenceError()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+ generator.Generate(typeof(CircularReferenceClass));
+ }
+
+ [Test]
+ public void CircularReferenceWithTypeNameId()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+ generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName;
+
+ JsonSchema schema = generator.Generate(typeof(CircularReferenceClass), true);
+
+ Assert.AreEqual(JsonSchemaType.String, schema.Properties["Name"].Type);
+ Assert.AreEqual(typeof(CircularReferenceClass).FullName, schema.Id);
+ Assert.AreEqual(JsonSchemaType.Object | JsonSchemaType.Null, schema.Properties["Child"].Type);
+ Assert.AreEqual(schema, schema.Properties["Child"]);
+ }
+
+ [Test]
+ public void CircularReferenceWithExplicitId()
+ {
+ JsonSchemaGenerator generator = new JsonSchemaGenerator();
+
+ JsonSchema schema = generator.Generate(typeof(CircularReferenceWithIdClass));
+
+ Assert.AreEqual(JsonSchemaType.String, schema.Properties["Name"].Type);
+ Assert.AreEqual("MyExplicitId", schema.Id);
+ Assert.AreEqual(JsonSchemaType.Object, schema.Properties["Child"].Type);
+ Assert.AreEqual(schema, schema.Properties["Child"]);
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaModelBuilderTests.cs b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaModelBuilderTests.cs
new file mode 100644
index 00000000..220047e8
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaModelBuilderTests.cs
@@ -0,0 +1,166 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Schema;
+using NUnit.Framework;
+
+namespace Newtonsoft.Json.Tests.Schema
+{
+ public class JsonSchemaModelBuilderTests : TestFixtureBase
+ {
+ [Test]
+ public void ExtendedComplex()
+ {
+ string first = @"{
+ ""id"":""first"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""firstproperty"":{""type"":""string""},
+ ""secondproperty"":{""type"":""string"",""maxLength"":10},
+ ""thirdproperty"":{
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""thirdproperty_firstproperty"":{""type"":""string"",""maxLength"":10,""minLength"":7}
+ }
+ }
+ },
+ ""additionalProperties"":{}
+}";
+
+ string second = @"{
+ ""id"":""second"",
+ ""type"":""object"",
+ ""extends"":{""$ref"":""first""},
+ ""properties"":
+ {
+ ""secondproperty"":{""type"":""any""},
+ ""thirdproperty"":{
+ ""extends"":{
+ ""properties"":
+ {
+ ""thirdproperty_firstproperty"":{""maxLength"":9,""minLength"":6,""pattern"":""hi2u""}
+ },
+ ""additionalProperties"":{""maxLength"":9,""minLength"":6,""enum"":[""one"",""two""]}
+ },
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""thirdproperty_firstproperty"":{""pattern"":""hi""}
+ },
+ ""additionalProperties"":{""type"":""string"",""enum"":[""two"",""three""]}
+ },
+ ""fourthproperty"":{""type"":""string""}
+ },
+ ""additionalProperties"":false
+}";
+
+ JsonSchemaResolver resolver = new JsonSchemaResolver();
+ JsonSchema firstSchema = JsonSchema.Parse(first, resolver);
+ JsonSchema secondSchema = JsonSchema.Parse(second, resolver);
+
+ JsonSchemaModelBuilder modelBuilder = new JsonSchemaModelBuilder();
+
+ JsonSchemaModel model = modelBuilder.Build(secondSchema);
+
+ Assert.AreEqual(4, model.Properties.Count);
+
+ Assert.AreEqual(JsonSchemaType.String, model.Properties["firstproperty"].Type);
+
+ Assert.AreEqual(JsonSchemaType.String, model.Properties["secondproperty"].Type);
+ Assert.AreEqual(10, model.Properties["secondproperty"].MaximumLength);
+ Assert.AreEqual(null, model.Properties["secondproperty"].Enum);
+ Assert.AreEqual(null, model.Properties["secondproperty"].Patterns);
+
+ Assert.AreEqual(JsonSchemaType.Object, model.Properties["thirdproperty"].Type);
+ Assert.AreEqual(3, model.Properties["thirdproperty"].AdditionalProperties.Enum.Count);
+ Assert.AreEqual("two", (string)model.Properties["thirdproperty"].AdditionalProperties.Enum[0]);
+ Assert.AreEqual("three", (string)model.Properties["thirdproperty"].AdditionalProperties.Enum[1]);
+ Assert.AreEqual("one", (string)model.Properties["thirdproperty"].AdditionalProperties.Enum[2]);
+
+ Assert.AreEqual(JsonSchemaType.String, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Type);
+ Assert.AreEqual(9, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].MaximumLength);
+ Assert.AreEqual(7, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].MinimumLength);
+ Assert.AreEqual(2, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Patterns.Count);
+ Assert.AreEqual("hi", model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Patterns[0]);
+ Assert.AreEqual("hi2u", model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Patterns[1]);
+ Assert.AreEqual(null, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Properties);
+ Assert.AreEqual(null, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Items);
+ Assert.AreEqual(null, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].AdditionalProperties);
+ }
+
+ [Test]
+ public void CircularReference()
+ {
+ string json = @"{
+ ""id"":""CircularReferenceArray"",
+ ""description"":""CircularReference"",
+ ""type"":[""array""],
+ ""items"":{""$ref"":""CircularReferenceArray""}
+}";
+
+ JsonSchema schema = JsonSchema.Parse(json);
+
+ JsonSchemaModelBuilder modelBuilder = new JsonSchemaModelBuilder();
+
+ JsonSchemaModel model = modelBuilder.Build(schema);
+
+ Assert.AreEqual(JsonSchemaType.Array, model.Type);
+
+ Assert.AreEqual(model, model.Items[0]);
+ }
+
+ [Test]
+ public void Optional()
+ {
+ string schemaJson = @"{
+ ""description"":""A person"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""name"":{""type"":""string""},
+ ""hobbies"":{""type"":""string"",optional:true},
+ ""age"":{""type"":""integer"",optional:true}
+ }
+}";
+
+ JsonSchema schema = JsonSchema.Parse(schemaJson);
+ JsonSchemaModelBuilder modelBuilder = new JsonSchemaModelBuilder();
+ JsonSchemaModel model = modelBuilder.Build(schema);
+
+ Assert.AreEqual(JsonSchemaType.Object, model.Type);
+ Assert.AreEqual(3, model.Properties.Count);
+ Assert.AreEqual(false, model.Properties["name"].Optional);
+ Assert.AreEqual(true, model.Properties["hobbies"].Optional);
+ Assert.AreEqual(true, model.Properties["age"].Optional);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaNodeTests.cs b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaNodeTests.cs
new file mode 100644
index 00000000..d5a8de12
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaNodeTests.cs
@@ -0,0 +1,118 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Schema;
+using NUnit.Framework;
+
+namespace Newtonsoft.Json.Tests.Schema
+{
+ public class JsonSchemaNodeTests : TestFixtureBase
+ {
+ [Test]
+ public void AddSchema()
+ {
+ string first = @"{
+ ""id"":""first"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""firstproperty"":{""type"":""string"",""maxLength"":10},
+ ""secondproperty"":{
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""secondproperty_firstproperty"":{""type"":""string"",""maxLength"":10,""minLength"":7}
+ }
+ }
+ },
+ ""additionalProperties"":{}
+}";
+
+ string second = @"{
+ ""id"":""second"",
+ ""type"":""object"",
+ ""extends"":{""$ref"":""first""},
+ ""properties"":
+ {
+ ""firstproperty"":{""type"":""string""},
+ ""secondproperty"":{
+ ""extends"":{
+ ""properties"":
+ {
+ ""secondproperty_firstproperty"":{""maxLength"":9,""minLength"":6}
+ }
+ },
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""secondproperty_firstproperty"":{}
+ }
+ },
+ ""thirdproperty"":{""type"":""string""}
+ },
+ ""additionalProperties"":false
+}";
+
+ JsonSchemaResolver resolver = new JsonSchemaResolver();
+ JsonSchema firstSchema = JsonSchema.Parse(first, resolver);
+ JsonSchema secondSchema = JsonSchema.Parse(second, resolver);
+
+ JsonSchemaModelBuilder modelBuilder = new JsonSchemaModelBuilder();
+
+ JsonSchemaNode node = modelBuilder.AddSchema(null, secondSchema);
+
+ Assert.AreEqual(2, node.Schemas.Count);
+ Assert.AreEqual(2, node.Properties["firstproperty"].Schemas.Count);
+ Assert.AreEqual(3, node.Properties["secondproperty"].Schemas.Count);
+ Assert.AreEqual(3, node.Properties["secondproperty"].Properties["secondproperty_firstproperty"].Schemas.Count);
+ }
+
+ [Test]
+ public void CircularReference()
+ {
+ string json = @"{
+ ""id"":""CircularReferenceArray"",
+ ""description"":""CircularReference"",
+ ""type"":[""array""],
+ ""items"":{""$ref"":""CircularReferenceArray""}
+}";
+
+ JsonSchema schema = JsonSchema.Parse(json);
+
+ JsonSchemaModelBuilder modelBuilder = new JsonSchemaModelBuilder();
+
+ JsonSchemaNode node = modelBuilder.AddSchema(null, schema);
+
+ Assert.AreEqual(1, node.Schemas.Count);
+
+ Assert.AreEqual(node, node.Items[0]);
+ }
+
+ }
+}
diff --git a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaTests.cs b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaTests.cs
new file mode 100644
index 00000000..4051ea95
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaTests.cs
@@ -0,0 +1,344 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Schema;
+using NUnit.Framework;
+
+namespace Newtonsoft.Json.Tests.Schema
+{
+ public class JsonSchemaTests : TestFixtureBase
+ {
+ [Test]
+ public void Extends()
+ {
+ string json;
+ JsonSchemaResolver resolver = new JsonSchemaResolver();
+
+ json = @"{
+ ""id"":""first"",
+ ""type"":""object"",
+ ""additionalProperties"":{}
+}";
+
+ JsonSchema first = JsonSchema.Parse(json, resolver);
+
+ json =
+ @"{
+ ""id"":""second"",
+ ""type"":""object"",
+ ""extends"":{""$ref"":""first""},
+ ""additionalProperties"":{""type"":""string""}
+}";
+
+ JsonSchema second = JsonSchema.Parse(json, resolver);
+ Assert.AreEqual(first, second.Extends);
+
+ json =
+ @"{
+ ""id"":""third"",
+ ""type"":""object"",
+ ""extends"":{""$ref"":""second""},
+ ""additionalProperties"":false
+}";
+
+ JsonSchema third = JsonSchema.Parse(json, resolver);
+ Assert.AreEqual(second, third.Extends);
+ Assert.AreEqual(first, third.Extends.Extends);
+
+ StringWriter writer = new StringWriter();
+ JsonTextWriter jsonWriter = new JsonTextWriter(writer);
+ jsonWriter.Formatting = Formatting.Indented;
+
+ third.WriteTo(jsonWriter, resolver);
+
+ string writtenJson = writer.ToString();
+ Assert.AreEqual(@"{
+ ""id"": ""third"",
+ ""type"": ""object"",
+ ""additionalProperties"": false,
+ ""extends"": {
+ ""$ref"": ""second""
+ }
+}", writtenJson);
+
+ StringWriter writer1 = new StringWriter();
+ JsonTextWriter jsonWriter1 = new JsonTextWriter(writer1);
+ jsonWriter1.Formatting = Formatting.Indented;
+
+ third.WriteTo(jsonWriter1);
+
+ writtenJson = writer1.ToString();
+ Assert.AreEqual(@"{
+ ""id"": ""third"",
+ ""type"": ""object"",
+ ""additionalProperties"": false,
+ ""extends"": {
+ ""id"": ""second"",
+ ""type"": ""object"",
+ ""additionalProperties"": {
+ ""type"": ""string""
+ },
+ ""extends"": {
+ ""id"": ""first"",
+ ""type"": ""object"",
+ ""additionalProperties"": {}
+ }
+ }
+}", writtenJson);
+ }
+ [Test]
+ public void WriteTo_AdditionalProperties()
+ {
+ StringWriter writer = new StringWriter();
+ JsonTextWriter jsonWriter = new JsonTextWriter(writer);
+ jsonWriter.Formatting = Formatting.Indented;
+
+ JsonSchema schema = JsonSchema.Parse(@"{
+ ""description"":""AdditionalProperties"",
+ ""type"":[""string"", ""integer""],
+ ""additionalProperties"":{""type"":[""object"", ""boolean""]}
+}");
+
+ schema.WriteTo(jsonWriter);
+
+ string json = writer.ToString();
+
+ Assert.AreEqual(@"{
+ ""description"": ""AdditionalProperties"",
+ ""type"": [
+ ""string"",
+ ""integer""
+ ],
+ ""additionalProperties"": {
+ ""type"": [
+ ""boolean"",
+ ""object""
+ ]
+ }
+}", json);
+ }
+
+ [Test]
+ public void WriteTo_Properties()
+ {
+ JsonSchema schema = JsonSchema.Parse(@"{
+ ""description"":""A person"",
+ ""type"":""object"",
+ ""properties"":
+ {
+ ""name"":{""type"":""string""},
+ ""hobbies"":
+ {
+ ""type"":""array"",
+ ""items"": {""type"":""string""}
+ }
+ }
+}");
+
+ StringWriter writer = new StringWriter();
+ JsonTextWriter jsonWriter = new JsonTextWriter(writer);
+ jsonWriter.Formatting = Formatting.Indented;
+
+ schema.WriteTo(jsonWriter);
+
+ string json = writer.ToString();
+
+ Assert.AreEqual(@"{
+ ""description"": ""A person"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""name"": {
+ ""type"": ""string""
+ },
+ ""hobbies"": {
+ ""type"": ""array"",
+ ""items"": {
+ ""type"": ""string""
+ }
+ }
+ }
+}", json);
+
+ }
+
+ [Test]
+ public void WriteTo_Enum()
+ {
+ JsonSchema schema = JsonSchema.Parse(@"{
+ ""description"":""Type"",
+ ""type"":[""string"",""array""],
+ ""items"":{},
+ ""enum"":[""string"",""object"",""array"",""boolean"",""number"",""integer"",""null"",""any""]
+}");
+
+ StringWriter writer = new StringWriter();
+ JsonTextWriter jsonWriter = new JsonTextWriter(writer);
+ jsonWriter.Formatting = Formatting.Indented;
+
+ schema.WriteTo(jsonWriter);
+
+ string json = writer.ToString();
+
+ Assert.AreEqual(@"{
+ ""description"": ""Type"",
+ ""type"": [
+ ""string"",
+ ""array""
+ ],
+ ""items"": {},
+ ""enum"": [
+ ""string"",
+ ""object"",
+ ""array"",
+ ""boolean"",
+ ""number"",
+ ""integer"",
+ ""null"",
+ ""any""
+ ]
+}", json);
+ }
+
+ [Test]
+ public void WriteTo_CircularReference()
+ {
+ string json = @"{
+ ""id"":""CircularReferenceArray"",
+ ""description"":""CircularReference"",
+ ""type"":[""array""],
+ ""items"":{""$ref"":""CircularReferenceArray""}
+}";
+
+ JsonSchema schema = JsonSchema.Parse(json);
+
+ StringWriter writer = new StringWriter();
+ JsonTextWriter jsonWriter = new JsonTextWriter(writer);
+ jsonWriter.Formatting = Formatting.Indented;
+
+ schema.WriteTo(jsonWriter);
+
+ string writtenJson = writer.ToString();
+
+ Assert.AreEqual(@"{
+ ""id"": ""CircularReferenceArray"",
+ ""description"": ""CircularReference"",
+ ""type"": ""array"",
+ ""items"": {
+ ""$ref"": ""CircularReferenceArray""
+ }
+}", writtenJson);
+ }
+
+ [Test]
+ public void WriteTo_DisallowMultiple()
+ {
+ JsonSchema schema = JsonSchema.Parse(@"{
+ ""description"":""Type"",
+ ""type"":[""string"",""array""],
+ ""items"":{},
+ ""disallow"":[""string"",""object"",""array""]
+}");
+
+ StringWriter writer = new StringWriter();
+ JsonTextWriter jsonWriter = new JsonTextWriter(writer);
+ jsonWriter.Formatting = Formatting.Indented;
+
+ schema.WriteTo(jsonWriter);
+
+ string json = writer.ToString();
+
+ Assert.AreEqual(@"{
+ ""description"": ""Type"",
+ ""type"": [
+ ""string"",
+ ""array""
+ ],
+ ""items"": {},
+ ""disallow"": [
+ ""string"",
+ ""object"",
+ ""array""
+ ]
+}", json);
+ }
+
+ [Test]
+ public void WriteTo_DisallowSingle()
+ {
+ JsonSchema schema = JsonSchema.Parse(@"{
+ ""description"":""Type"",
+ ""type"":[""string"",""array""],
+ ""items"":{},
+ ""disallow"":""any""
+}");
+
+ StringWriter writer = new StringWriter();
+ JsonTextWriter jsonWriter = new JsonTextWriter(writer);
+ jsonWriter.Formatting = Formatting.Indented;
+
+ schema.WriteTo(jsonWriter);
+
+ string json = writer.ToString();
+
+ Assert.AreEqual(@"{
+ ""description"": ""Type"",
+ ""type"": [
+ ""string"",
+ ""array""
+ ],
+ ""items"": {},
+ ""disallow"": ""any""
+}", json);
+ }
+
+ [Test]
+ public void WriteTo_MultipleItems()
+ {
+ JsonSchema schema = JsonSchema.Parse(@"{
+ ""items"":[{},{}]
+}");
+
+ StringWriter writer = new StringWriter();
+ JsonTextWriter jsonWriter = new JsonTextWriter(writer);
+ jsonWriter.Formatting = Formatting.Indented;
+
+ schema.WriteTo(jsonWriter);
+
+ string json = writer.ToString();
+
+ Assert.AreEqual(@"{
+ ""items"": [
+ {},
+ {}
+ ]
+}", json);
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/AbstractGenericBase.cs b/Src/Newtonsoft.Json.Tests/TestObjects/AbstractGenericBase.cs
new file mode 100644
index 00000000..50d510ed
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/AbstractGenericBase.cs
@@ -0,0 +1,32 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public abstract class AbstractGenericBase
+ {
+ public abstract TKey Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ArgumentConverterPrecedenceClassConverter.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ArgumentConverterPrecedenceClassConverter.cs
new file mode 100644
index 00000000..c7e46a20
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ArgumentConverterPrecedenceClassConverter.cs
@@ -0,0 +1,35 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class ArgumentConverterPrecedenceClassConverter : ConverterPrecedenceClassConverter
+ {
+ public override string ConverterType
+ {
+ get { return "Argument"; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/Article.cs b/Src/Newtonsoft.Json.Tests/TestObjects/Article.cs
new file mode 100644
index 00000000..2139c4c4
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/Article.cs
@@ -0,0 +1,41 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class Article
+ {
+ public string Name;
+
+ public Article()
+ {
+ }
+
+ public Article(string name)
+ {
+ Name = name;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ArticleCollection.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ArticleCollection.cs
new file mode 100644
index 00000000..3a1198bf
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ArticleCollection.cs
@@ -0,0 +1,33 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class ArticleCollection : List
+ {
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/BadJsonPropertyClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/BadJsonPropertyClass.cs
new file mode 100644
index 00000000..5190017e
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/BadJsonPropertyClass.cs
@@ -0,0 +1,35 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class BadJsonPropertyClass
+ {
+ [JsonProperty("pie")]
+ public string Pie = "Yum";
+
+ public string pie = "PieChart!";
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/CircularReferenceClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/CircularReferenceClass.cs
new file mode 100644
index 00000000..fe92bd1d
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/CircularReferenceClass.cs
@@ -0,0 +1,39 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class CircularReferenceClass
+ {
+ [JsonProperty(IsRequired = true)]
+ public string Name { get; set; }
+ public CircularReferenceClass Child { get; set; }
+ }
+}
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/CircularReferenceWithIdClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/CircularReferenceWithIdClass.cs
new file mode 100644
index 00000000..8c182413
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/CircularReferenceWithIdClass.cs
@@ -0,0 +1,40 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ [JsonObject(Id = "MyExplicitId")]
+ public class CircularReferenceWithIdClass
+ {
+ [JsonProperty(IsRequired = true)]
+ public string Name { get; set; }
+ public CircularReferenceWithIdClass Child { get; set; }
+ }
+}
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ClassAndMemberConverterClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ClassAndMemberConverterClass.cs
new file mode 100644
index 00000000..83dc2397
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ClassAndMemberConverterClass.cs
@@ -0,0 +1,34 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class ClassAndMemberConverterClass
+ {
+ public ConverterPrecedenceClass DefaultConverter { get; set; }
+ [JsonConverter(typeof(MemberConverterPrecedenceClassConverter))]
+ public ConverterPrecedenceClass MemberConverter { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ClassConverterPrecedenceClassConverter.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ClassConverterPrecedenceClassConverter.cs
new file mode 100644
index 00000000..90b12363
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ClassConverterPrecedenceClassConverter.cs
@@ -0,0 +1,35 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class ClassConverterPrecedenceClassConverter : ConverterPrecedenceClassConverter
+ {
+ public override string ConverterType
+ {
+ get { return "Class"; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ClassWithArray.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ClassWithArray.cs
new file mode 100644
index 00000000..971fc422
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ClassWithArray.cs
@@ -0,0 +1,54 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class ClassWithArray
+ {
+ private readonly IList bar;
+ private string foo;
+
+ public ClassWithArray()
+ {
+ bar = new List() { int.MaxValue };
+ }
+
+ [JsonProperty("foo")]
+ public string Foo
+ {
+ get { return foo; }
+ set { foo = value; }
+ }
+
+ [JsonProperty(PropertyName = "bar")]
+ public IList Bar
+ {
+ get { return bar; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ClassWithGuid.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ClassWithGuid.cs
new file mode 100644
index 00000000..84141fd6
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ClassWithGuid.cs
@@ -0,0 +1,34 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class ClassWithGuid
+ {
+ public Guid GuidField;
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ConstructorCaseSensitivityClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ConstructorCaseSensitivityClass.cs
new file mode 100644
index 00000000..41e535d6
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ConstructorCaseSensitivityClass.cs
@@ -0,0 +1,41 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class ConstructorCaseSensitivityClass
+ {
+ public string param1 { get; set; }
+ public string Param1 { get; set; }
+ public string Param2 { get; set; }
+
+ public ConstructorCaseSensitivityClass(string param1, string Param1, string param2)
+ {
+ this.param1 = param1;
+ this.Param1 = Param1;
+ this.Param2 = param2;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ConverableMembers.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ConverableMembers.cs
new file mode 100644
index 00000000..9b2e1014
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ConverableMembers.cs
@@ -0,0 +1,48 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ [JsonObject]
+ public class ConverableMembers
+ {
+ public string String = "string";
+ public int Int32 = int.MaxValue;
+ public uint UInt32 = uint.MaxValue;
+ public byte Byte = byte.MaxValue;
+ public sbyte SByte = sbyte.MaxValue;
+ public short Short = short.MaxValue;
+ public ushort UShort = ushort.MaxValue;
+ public long Long = long.MaxValue;
+ public ulong ULong = long.MaxValue;
+ public double Double = double.MaxValue;
+ public float Float = float.MaxValue;
+ public DBNull DBNull = DBNull.Value;
+ public bool Bool = true;
+ public char Char = '\0';
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ConverterPrecedenceClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ConverterPrecedenceClass.cs
new file mode 100644
index 00000000..dfd2e2bd
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ConverterPrecedenceClass.cs
@@ -0,0 +1,38 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ [JsonConverter(typeof(ClassConverterPrecedenceClassConverter))]
+ public class ConverterPrecedenceClass
+ {
+ public string TestValue { get; set; }
+
+ public ConverterPrecedenceClass(string testValue)
+ {
+ TestValue = testValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ConverterPrecedenceClassConverter.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ConverterPrecedenceClassConverter.cs
new file mode 100644
index 00000000..7f587986
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ConverterPrecedenceClassConverter.cs
@@ -0,0 +1,63 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public abstract class ConverterPrecedenceClassConverter : JsonConverter
+ {
+ public abstract string ConverterType { get; }
+
+ public override void WriteJson(JsonWriter writer, object value)
+ {
+ ConverterPrecedenceClass c = (ConverterPrecedenceClass)value;
+
+ JToken j = new JArray(ConverterType, c.TestValue);
+
+ j.WriteTo(writer);
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType)
+ {
+ JToken j = JArray.Load(reader);
+
+ string converter = (string)j[0];
+ if (converter != ConverterType)
+ throw new Exception(StringUtils.FormatWith("Serialize converter {0} and deserialize converter {1} do not match.", CultureInfo.InvariantCulture, converter, ConverterType));
+
+ string testValue = (string)j[1];
+ return new ConverterPrecedenceClass(testValue);
+ }
+
+ public override bool CanConvert(Type objectType)
+ {
+ return (objectType == typeof(ConverterPrecedenceClass));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/DateTimeTestClass.cs
similarity index 94%
rename from Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs
rename to Src/Newtonsoft.Json.Tests/TestObjects/DateTimeTestClass.cs
index ad79bd7e..fe49cd32 100644
--- a/Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/DateTimeTestClass.cs
@@ -28,7 +28,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
-namespace Newtonsoft.Json.Tests
+namespace Newtonsoft.Json.Tests.TestObjects
{
public class DateTimeTestClass
{
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/DefaultValueAttributeTestClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/DefaultValueAttributeTestClass.cs
new file mode 100644
index 00000000..861c709a
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/DefaultValueAttributeTestClass.cs
@@ -0,0 +1,41 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.ComponentModel;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+#if !PocketPC
+ [Description("DefaultValueAttributeTestClass description!")]
+#endif
+ public class DefaultValueAttributeTestClass
+ {
+ [DefaultValue("TestProperty1Value")]
+ public string TestProperty1 { get; set; }
+
+ [DefaultValue(21)]
+ public int TestField1;
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/DoubleClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/DoubleClass.cs
new file mode 100644
index 00000000..2de57336
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/DoubleClass.cs
@@ -0,0 +1,32 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class DoubleClass
+ {
+ public double? Height { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/GenericImpl.cs b/Src/Newtonsoft.Json.Tests/TestObjects/GenericImpl.cs
new file mode 100644
index 00000000..cd6d11a1
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/GenericImpl.cs
@@ -0,0 +1,32 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class GenericImpl : AbstractGenericBase
+ {
+ public override int Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/GetOnlyPropertyClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/GetOnlyPropertyClass.cs
new file mode 100644
index 00000000..a45ffcee
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/GetOnlyPropertyClass.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class GetOnlyPropertyClass
+ {
+ public string Field = "Field";
+
+ public string GetOnlyProperty
+ {
+ get { return "GetOnlyProperty"; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/IncompatibleJsonAttributeClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/IncompatibleJsonAttributeClass.cs
new file mode 100644
index 00000000..eb86156e
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/IncompatibleJsonAttributeClass.cs
@@ -0,0 +1,34 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using Newtonsoft.Json.Converters;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ [JsonConverter(typeof(IsoDateTimeConverter))]
+ public class IncompatibleJsonAttributeClass
+ {
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/Invoice.cs b/Src/Newtonsoft.Json.Tests/TestObjects/Invoice.cs
new file mode 100644
index 00000000..7d0554b6
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/Invoice.cs
@@ -0,0 +1,40 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.ComponentModel;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class Invoice
+ {
+ public string Company { get; set; }
+ public decimal Amount { get; set; }
+ [DefaultValue(false)]
+ public bool Paid { get; set; }
+ [DefaultValue(null)]
+ public DateTime? PaidDate { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/JsonIgnoreAttributeOnClassTestClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/JsonIgnoreAttributeOnClassTestClass.cs
new file mode 100644
index 00000000..733c8d0c
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/JsonIgnoreAttributeOnClassTestClass.cs
@@ -0,0 +1,52 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ [JsonObject(MemberSerialization.OptIn)]
+ public class JsonIgnoreAttributeOnClassTestClass
+ {
+ private int _property = 21;
+ private int _ignoredProperty = 12;
+
+ [JsonProperty("TheField")]
+ public int Field;
+
+ [JsonProperty]
+ public int Property
+ {
+ get { return _property; }
+ }
+
+ public int IgnoredField;
+
+ [JsonProperty]
+ [JsonIgnore] // JsonIgnore should take priority
+ public int IgnoredProperty
+ {
+ get { return _ignoredProperty; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/JsonIgnoreAttributeTestClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/JsonIgnoreAttributeTestClass.cs
new file mode 100644
index 00000000..bf688271
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/JsonIgnoreAttributeTestClass.cs
@@ -0,0 +1,51 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class JsonIgnoreAttributeTestClass
+ {
+ private int _property = 21;
+ private int _ignoredProperty = 12;
+
+ public int Field;
+ public int Property
+ {
+ get { return _property; }
+ }
+
+ [JsonIgnore]
+ public int IgnoredField;
+
+ [JsonIgnore]
+ public int IgnoredProperty
+ {
+ get { return _ignoredProperty; }
+ }
+
+ [JsonIgnore]
+ public Product IgnoredObject = new Product();
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/MemberConverterClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/MemberConverterClass.cs
new file mode 100644
index 00000000..4a5e983c
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/MemberConverterClass.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Converters;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class MemberConverterClass
+ {
+ public DateTime DefaultConverter { get; set; }
+ [JsonConverter(typeof(IsoDateTimeConverter))]
+ public DateTime MemberConverter { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/MemberConverterPrecedenceClassConverter.cs b/Src/Newtonsoft.Json.Tests/TestObjects/MemberConverterPrecedenceClassConverter.cs
new file mode 100644
index 00000000..8df807fb
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/MemberConverterPrecedenceClassConverter.cs
@@ -0,0 +1,35 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class MemberConverterPrecedenceClassConverter : ConverterPrecedenceClassConverter
+ {
+ public override string ConverterType
+ {
+ get { return "Member"; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/MethodExecutorObject.cs b/Src/Newtonsoft.Json.Tests/TestObjects/MethodExecutorObject.cs
new file mode 100644
index 00000000..c7c5edd4
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/MethodExecutorObject.cs
@@ -0,0 +1,34 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class MethodExecutorObject
+ {
+ public string serverClassName;
+ public object[] serverMethodParams;
+ public string clientGetResultFunction;
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/MyClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/MyClass.cs
new file mode 100644
index 00000000..f80a2c54
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/MyClass.cs
@@ -0,0 +1,34 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class MyClass
+ {
+ public int PreProperty { get; set; }
+ //public DateTime DateProperty { get; set; }
+ public int PostProperty { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/Name.cs b/Src/Newtonsoft.Json.Tests/TestObjects/Name.cs
new file mode 100644
index 00000000..5663e00b
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/Name.cs
@@ -0,0 +1,41 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class Name
+ {
+ public string personsName;
+
+ public List pNumbers = new List();
+
+ public Name(string personsName)
+ {
+ this.personsName = personsName;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/Person.cs b/Src/Newtonsoft.Json.Tests/TestObjects/Person.cs
new file mode 100644
index 00000000..159473c9
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/Person.cs
@@ -0,0 +1,54 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.ComponentModel;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ [JsonObject(Id = "Person", Title = "Title!", Description = "JsonObjectAttribute description!", MemberSerialization = MemberSerialization.OptIn)]
+#if !PocketPC
+ [Description("DescriptionAttribute description!")]
+#endif
+ public class Person
+ {
+ // "John Smith"
+ [JsonProperty]
+ public string Name { get; set; }
+
+ // "2000-12-15T22:11:03"
+ [JsonProperty]
+ //[JsonConverter(typeof(IsoDateTimeConverter))]
+ public DateTime BirthDate { get; set; }
+
+ // new Date(976918263055)
+ [JsonProperty]
+ //[JsonConverter(typeof(JavaScriptDateTimeConverter))]
+ public DateTime LastModified { get; set; }
+
+ // not serialized
+ public string Department { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/PersonRaw.cs b/Src/Newtonsoft.Json.Tests/TestObjects/PersonRaw.cs
new file mode 100644
index 00000000..2797fff2
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/PersonRaw.cs
@@ -0,0 +1,64 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class PersonRaw
+ {
+ private Guid _internalId;
+ private string _firstName;
+ private string _lastName;
+ private JsonRaw _rawContent;
+
+ [JsonIgnore]
+ public Guid InternalId
+ {
+ get { return _internalId; }
+ set { _internalId = value; }
+ }
+
+ [JsonProperty("first_name")]
+ public string FirstName
+ {
+ get { return _firstName; }
+ set { _firstName = value; }
+ }
+
+ public JsonRaw RawContent
+ {
+ get { return _rawContent; }
+ set { _rawContent = value; }
+ }
+
+ [JsonProperty("last_name")]
+ public string LastName
+ {
+ get { return _lastName; }
+ set { _lastName = value; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/PhoneNumber.cs b/Src/Newtonsoft.Json.Tests/TestObjects/PhoneNumber.cs
new file mode 100644
index 00000000..541b2fe0
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/PhoneNumber.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class PhoneNumber
+ {
+ public string phoneNumber;
+
+ public PhoneNumber(string phoneNumber)
+ {
+ this.phoneNumber = phoneNumber;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/Product.cs b/Src/Newtonsoft.Json.Tests/TestObjects/Product.cs
new file mode 100644
index 00000000..46698794
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/Product.cs
@@ -0,0 +1,54 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class Product
+ {
+ public string Name;
+ public DateTime Expiry = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ public decimal Price;
+ public string[] Sizes;
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Product)
+ {
+ Product p = (Product)obj;
+
+ return (p.Name == Name && p.Expiry == Expiry && p.Price == Price);
+ }
+
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return (Name ?? string.Empty).GetHashCode();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ProductCollection.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ProductCollection.cs
new file mode 100644
index 00000000..c2ae8541
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ProductCollection.cs
@@ -0,0 +1,33 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class ProductCollection : List
+ {
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/ProductShort.cs b/Src/Newtonsoft.Json.Tests/TestObjects/ProductShort.cs
new file mode 100644
index 00000000..718d2aa9
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/ProductShort.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class ProductShort
+ {
+ public string Name;
+ public DateTime Expiry;
+ //public decimal Price;
+ public string[] Sizes;
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/RequiredMembersClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/RequiredMembersClass.cs
new file mode 100644
index 00000000..ae62e9d8
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/RequiredMembersClass.cs
@@ -0,0 +1,47 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class RequiredMembersClass
+ {
+ [JsonProperty(IsRequired = true)]
+ public string FirstName { get; set; }
+
+ [JsonProperty]
+ public string MiddleName { get; set; }
+
+ [JsonProperty(IsRequired = true)]
+ public string LastName { get; set; }
+
+ [JsonProperty(IsRequired = true)]
+ public DateTime BirthDate { get; set; }
+ }
+}
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/SetOnlyPropertyClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/SetOnlyPropertyClass.cs
new file mode 100644
index 00000000..5af03cd2
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/SetOnlyPropertyClass.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class SetOnlyPropertyClass
+ {
+ public string Field = "Field";
+
+ public string SetOnlyProperty
+ {
+ set { }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/Store.cs b/Src/Newtonsoft.Json.Tests/TestObjects/Store.cs
new file mode 100644
index 00000000..faffddb8
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/Store.cs
@@ -0,0 +1,62 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class Store
+ {
+ public StoreColor Color = StoreColor.Yellow;
+ public DateTimeOffset Establised = new DateTimeOffset(2010, 1, 22, 1, 1, 1, TimeSpan.Zero);
+ public double Width = 1.1;
+ public int Employees = 999;
+ public int[] RoomsPerFloor = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ public bool Open = false;
+ public char Symbol = '@';
+ public List Mottos = new List();
+ public decimal Cost = 100980.1M;
+ public string Escape = "\r\n\t\f\b?{\\r\\n\"\'";
+ public List product = new List();
+
+ public Store()
+ {
+ Mottos.Add("Hello World");
+ Mottos.Add("öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~");
+ Mottos.Add(null);
+ Mottos.Add(" ");
+
+ Product rocket = new Product();
+ rocket.Name = "Rocket";
+ rocket.Expiry = new DateTime(2000, 2, 2, 23, 1, 30, DateTimeKind.Utc);
+ Product alien = new Product();
+ alien.Name = "Alien";
+
+ product.Add(rocket);
+ product.Add(alien);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/StoreColor.cs b/Src/Newtonsoft.Json.Tests/TestObjects/StoreColor.cs
new file mode 100644
index 00000000..43cf7fbc
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/StoreColor.cs
@@ -0,0 +1,35 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public enum StoreColor
+ {
+ Black,
+ Red,
+ Yellow,
+ White
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/TypeClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/TypeClass.cs
new file mode 100644
index 00000000..5bf2fc9b
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/TypeClass.cs
@@ -0,0 +1,34 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class TypeClass
+ {
+ public Type TypeProperty { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/TypedSubHashtable.cs b/Src/Newtonsoft.Json.Tests/TestObjects/TypedSubHashtable.cs
new file mode 100644
index 00000000..1c8efe8b
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/TypedSubHashtable.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+#if !SILVERLIGHT
+ public class TypedSubHashtable
+ {
+ public string Name;
+ public Hashtable Hash;
+ }
+#endif
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/UserNullable.cs b/Src/Newtonsoft.Json.Tests/TestObjects/UserNullable.cs
new file mode 100644
index 00000000..9c16dbe7
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/TestObjects/UserNullable.cs
@@ -0,0 +1,40 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Tests.TestObjects
+{
+ public class UserNullable
+ {
+ public Guid Id;
+ public string FName;
+ public string LName;
+ public int RoleId;
+ public int? NullableRoleId;
+ public int? NullRoleId;
+ public bool? Active;
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonArrayAttribute.cs b/Src/Newtonsoft.Json/JsonArrayAttribute.cs
new file mode 100644
index 00000000..4ea4b400
--- /dev/null
+++ b/Src/Newtonsoft.Json/JsonArrayAttribute.cs
@@ -0,0 +1,72 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the how to serialize the object.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
+ public sealed class JsonArrayAttribute : JsonContainerAttribute
+ {
+ private bool _allowNullItems;
+
+ public bool AllowNullItems
+ {
+ get { return _allowNullItems; }
+ set { _allowNullItems = value; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonArrayAttribute()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with a flag indicating whether the array can contain null items
+ ///
+ /// A flag indicating whether the array can contain null items.
+ public JsonArrayAttribute(bool allowNullItems)
+ {
+ _allowNullItems = allowNullItems;
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified container Id.
+ ///
+ /// The container Id.
+ public JsonArrayAttribute(string id)
+ : base(id)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonContainerAttribute.cs b/Src/Newtonsoft.Json/JsonContainerAttribute.cs
new file mode 100644
index 00000000..bb88c168
--- /dev/null
+++ b/Src/Newtonsoft.Json/JsonContainerAttribute.cs
@@ -0,0 +1,59 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+ ///
+ /// Instructs the how to serialize the object.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
+ public abstract class JsonContainerAttribute : Attribute
+ {
+ public string Id { get; set; }
+ public string Title { get; set; }
+ public string Description { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JsonContainerAttribute()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class with the specified container Id.
+ ///
+ /// The container Id.
+ public JsonContainerAttribute(string id)
+ {
+ Id = id;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs
index dc8226e7..2fa505f3 100644
--- a/Src/Newtonsoft.Json/JsonConvert.cs
+++ b/Src/Newtonsoft.Json/JsonConvert.cs
@@ -38,7 +38,7 @@ using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json
{
///
- /// Provides methods for converting between common language runtime types and JavaScript types.
+ /// Provides methods for converting between common language runtime types and JSON types.
///
public static class JsonConvert
{
@@ -255,7 +255,7 @@ namespace Newtonsoft.Json
/// A Json string representation of the .
public static string ToString(float value)
{
- return value.ToString("R", CultureInfo.InvariantCulture);
+ return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
}
///
@@ -265,7 +265,15 @@ namespace Newtonsoft.Json
/// A Json string representation of the .
public static string ToString(double value)
{
- return value.ToString("R", CultureInfo.InvariantCulture);
+ return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
+ }
+
+ private static string EnsureDecimalPlace(double value, string text)
+ {
+ if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1)
+ return text;
+
+ return text + ".0";
}
///
diff --git a/Src/Newtonsoft.Json/JsonObjectAttribute.cs b/Src/Newtonsoft.Json/JsonObjectAttribute.cs
index 568b71e9..79b5e8b2 100644
--- a/Src/Newtonsoft.Json/JsonObjectAttribute.cs
+++ b/Src/Newtonsoft.Json/JsonObjectAttribute.cs
@@ -34,7 +34,7 @@ namespace Newtonsoft.Json
/// Instructs the how to serialize the object.
///
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
- public sealed class JsonObjectAttribute : Attribute
+ public sealed class JsonObjectAttribute : JsonContainerAttribute
{
private MemberSerialization _memberSerialization = MemberSerialization.OptOut;
@@ -63,5 +63,14 @@ namespace Newtonsoft.Json
{
MemberSerialization = memberSerialization;
}
+
+ ///
+ /// Initializes a new instance of the class with the specified container Id.
+ ///
+ /// The container Id.
+ public JsonObjectAttribute(string id)
+ : base(id)
+ {
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonPropertyAttribute.cs b/Src/Newtonsoft.Json/JsonPropertyAttribute.cs
index e6049ea8..c05f449e 100644
--- a/Src/Newtonsoft.Json/JsonPropertyAttribute.cs
+++ b/Src/Newtonsoft.Json/JsonPropertyAttribute.cs
@@ -9,6 +9,7 @@ namespace Newtonsoft.Json
public sealed class JsonPropertyAttribute : Attribute
{
private string _propertyName;
+ private bool _isRequired;
///
/// Gets or sets the name of the property.
@@ -20,6 +21,12 @@ namespace Newtonsoft.Json
set { _propertyName = value; }
}
+ public bool IsRequired
+ {
+ get { return _isRequired; }
+ set { _isRequired = value; }
+ }
+
///
/// Initializes a new instance of the class.
///
diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs
index cc3ab4c9..7dd7dd7d 100644
--- a/Src/Newtonsoft.Json/JsonReader.cs
+++ b/Src/Newtonsoft.Json/JsonReader.cs
@@ -25,9 +25,7 @@
using System;
using System.Collections.Generic;
-using System.Text;
using System.IO;
-using System.Xml;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Utilities;
@@ -117,21 +115,21 @@ namespace Newtonsoft.Json
private int _top;
- private List _stack;
+ private readonly List _stack;
///
/// Gets the quotation mark character used to enclose the value of a string.
///
- public char QuoteChar
+ public virtual char QuoteChar
{
get { return _quoteChar; }
- protected set { _quoteChar = value; }
+ protected internal set { _quoteChar = value; }
}
///
/// Gets the type of the current Json token.
///
- public JsonToken TokenType
+ public virtual JsonToken TokenType
{
get { return _token; }
}
@@ -139,7 +137,7 @@ namespace Newtonsoft.Json
///
/// Gets the text value of the current Json token.
///
- public object Value
+ public virtual object Value
{
get { return _value; }
}
@@ -147,7 +145,7 @@ namespace Newtonsoft.Json
///
/// Gets The Common Language Runtime (CLR) type for the current Json token.
///
- public Type ValueType
+ public virtual Type ValueType
{
get { return _valueType; }
}
@@ -156,7 +154,7 @@ namespace Newtonsoft.Json
/// Gets the depth of the current token in the JSON document.
///
/// The depth of the current token in the JSON document.
- public int Depth
+ public virtual int Depth
{
get
{
@@ -331,7 +329,7 @@ namespace Newtonsoft.Json
}
}
- private bool IsStartToken(JsonToken token)
+ internal static bool IsStartToken(JsonToken token)
{
switch (token)
{
diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs
index d282ba6b..511e8ecd 100644
--- a/Src/Newtonsoft.Json/JsonSerializer.cs
+++ b/Src/Newtonsoft.Json/JsonSerializer.cs
@@ -30,6 +30,7 @@ using System.IO;
using System.Collections;
using System.Reflection;
using System.ComponentModel;
+using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Utilities;
using System.Globalization;
using System.Linq;
@@ -44,9 +45,7 @@ namespace Newtonsoft.Json
///
public class JsonSerializer
{
- private static readonly Dictionary ConverterTypeCache = new Dictionary();
- private static readonly Dictionary TypeMemberMappingsCache = new Dictionary();
-
+ #region Properties
private ReferenceLoopHandling _referenceLoopHandling;
private MissingMemberHandling _missingMemberHandling;
private ObjectCreationHandling _objectCreationHandling;
@@ -145,6 +144,7 @@ namespace Newtonsoft.Json
return _converters;
}
}
+ #endregion
///
/// Initializes a new instance of the class.
@@ -244,7 +244,7 @@ namespace Newtonsoft.Json
if (objectType == null)
throw new ArgumentNullException("objectType");
- converter = GetConverter(objectType, objectType);
+ converter = JsonTypeReflector.GetConverter(objectType, objectType);
return (converter != null);
}
@@ -282,7 +282,7 @@ namespace Newtonsoft.Json
{
value = CreateJToken(reader);
}
- else if (typeof(IDictionary).IsAssignableFrom(objectType) || ReflectionUtils.ImplementsGenericDefinition(objectType, typeof(IDictionary<,>)))
+ else if (CollectionUtils.IsDictionaryType(objectType))
{
if (existingValue == null)
value = CreateAndPopulateDictionary(reader, objectType);
@@ -363,110 +363,16 @@ namespace Newtonsoft.Json
}
}
- private MemberMappingCollection GetMemberMappings(Type objectType)
+ protected virtual JsonMemberMappingCollection GetMemberMappings(Type objectType)
{
- MemberMappingCollection memberMappings;
+ ValidationUtils.ArgumentNotNull(objectType, "objectType");
- if (TypeMemberMappingsCache.TryGetValue(objectType, out memberMappings))
- return memberMappings;
-
- memberMappings = CreateMemberMappings(objectType);
- TypeMemberMappingsCache[objectType] = memberMappings;
-
- return memberMappings;
- }
-
- private MemberMappingCollection CreateMemberMappings(Type objectType)
- {
- MemberSerialization memberSerialization = GetObjectMemberSerialization(objectType);
-
- List members = GetSerializableMembers(objectType);
- if (members == null)
- throw new JsonSerializationException("Null collection of seralizable members returned.");
-
- MemberMappingCollection memberMappings = new MemberMappingCollection();
-
- foreach (MemberInfo member in members)
- {
- JsonPropertyAttribute propertyAttribute = ReflectionUtils.GetAttribute(member, true);
- bool hasIgnoreAttribute = member.IsDefined(typeof(JsonIgnoreAttribute), true);
-
- string mappedName = (propertyAttribute != null && propertyAttribute.PropertyName != null)
- ? propertyAttribute.PropertyName
- : member.Name;
-
- bool ignored = (hasIgnoreAttribute
- || (memberSerialization == MemberSerialization.OptIn && propertyAttribute == null));
-
- bool readable = ReflectionUtils.CanReadMemberValue(member);
- bool writable = ReflectionUtils.CanSetMemberValue(member);
-
- JsonConverter memberConverter = GetConverter(member, ReflectionUtils.GetMemberUnderlyingType(member));
-
- DefaultValueAttribute defaultValueAttribute = ReflectionUtils.GetAttribute(member, true);
- object defaultValue = (defaultValueAttribute != null) ? defaultValueAttribute.Value : null;
-
- MemberMapping memberMapping = new MemberMapping(mappedName, member, ignored, readable, writable, memberConverter, defaultValue);
-
- memberMappings.AddMapping(memberMapping);
- }
-
- return memberMappings;
- }
-
- ///
- /// Gets the serializable members for the given .
- ///
- /// The object to get seralizable members for.
- /// Seralizable members for the given type.
- protected virtual List GetSerializableMembers(Type objectType)
- {
- return ReflectionUtils.GetFieldsAndProperties(objectType, BindingFlags.Public | BindingFlags.Instance);
- }
-
- private static MemberSerialization GetObjectMemberSerialization(Type objectType)
- {
- JsonObjectAttribute objectAttribute = ReflectionUtils.GetAttribute(objectType, true);
-
- if (objectAttribute == null)
- return MemberSerialization.OptOut;
- else
- return objectAttribute.MemberSerialization;
- }
-
- private JsonConverter GetConverter(ICustomAttributeProvider attributeProvider, Type targetConvertedType)
- {
- Type converterType;
-
- if (!ConverterTypeCache.TryGetValue(attributeProvider, out converterType))
- {
- JsonConverterAttribute converterAttribute = ReflectionUtils.GetAttribute(attributeProvider, true);
- converterType = (converterAttribute != null)
- ? converterAttribute.ConverterType
- : null;
-
- ConverterTypeCache[attributeProvider] = converterType;
- }
-
- if (converterType != null)
- {
- JsonConverter memberConverter = JsonConverterAttribute.CreateJsonConverterInstance(converterType);
-
- if (!memberConverter.CanConvert(targetConvertedType))
- throw new JsonSerializationException("JsonConverter {0} on {1} is not compatible with member type {2}.".FormatWith(CultureInfo.InvariantCulture, memberConverter.GetType().Name, attributeProvider, targetConvertedType.Name));
-
- return memberConverter;
- }
-
- return null;
+ return JsonTypeReflector.GetMemberMappings(objectType);
}
private void SetObjectMember(JsonReader reader, object target, Type targetType, string memberName)
{
- if (!reader.Read())
- throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
-
- MemberMappingCollection memberMappings = GetMemberMappings(targetType);
+ JsonMemberMappingCollection memberMappings = GetMemberMappings(targetType);
Type memberType;
object value;
@@ -474,7 +380,7 @@ namespace Newtonsoft.Json
// otherwise test if target is a dictionary and assign value with the key if it is
if (memberMappings.Contains(memberName))
{
- MemberMapping memberMapping = memberMappings[memberName];
+ JsonMemberMapping memberMapping = memberMappings[memberName];
if (memberMapping.Ignored)
{
@@ -503,7 +409,7 @@ namespace Newtonsoft.Json
return;
}
- value = CreateObject(reader, memberType, (useExistingValue) ? currentValue : null, GetConverter(memberMapping.Member, memberType));
+ value = CreateObject(reader, memberType, (useExistingValue) ? currentValue : null, JsonTypeReflector.GetConverter(memberMapping.Member, memberType));
if (_nullValueHandling == NullValueHandling.Ignore && value == null)
return;
@@ -603,7 +509,7 @@ namespace Newtonsoft.Json
// create a dictionary to put retrieved values into
IDictionary constructorParameters = c.GetParameters().ToDictionary(p => p, p => (object)null);
- MemberMappingCollection mappings = GetMemberMappings(objectType);
+ JsonMemberMappingCollection mappings = GetMemberMappings(objectType);
bool exit = false;
while (!exit && reader.Read())
@@ -616,7 +522,7 @@ namespace Newtonsoft.Json
throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, memberName).Key;
- MemberMapping mapping;
+ JsonMemberMapping mapping;
if (matchingConstructorParameter != null && mappings.TryGetMapping(memberName, out mapping) && !mapping.Ignored)
{
@@ -644,6 +550,15 @@ namespace Newtonsoft.Json
private object PopulateObject(object newObject, JsonReader reader, Type objectType)
{
+ JsonMemberMappingCollection memberMappings = GetMemberMappings(objectType);
+ Dictionary requiredMappings =
+ memberMappings.Where(m => m.Required).ToDictionary(m => m.MappingName, m => false);
+ //List requiredMappingContexts =
+ // memberMappings.Where(m => m.Required).Select(m => new RequiredMemberContext(m.MappingName, false)).ToList();
+
+ //ObjectContext context = new ObjectContext(newObject, requiredMappingContexts);
+ //DeserializeStack.Add(context);
+
while (reader.Read())
{
switch (reader.TokenType)
@@ -651,9 +566,25 @@ namespace Newtonsoft.Json
case JsonToken.PropertyName:
string memberName = reader.Value.ToString();
+ if (!reader.Read())
+ throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
+
+ if (reader.TokenType != JsonToken.Null)
+ {
+ if (requiredMappings.ContainsKey(memberName))
+ requiredMappings[memberName] = true;
+ }
+
SetObjectMember(reader, newObject, objectType, memberName);
break;
case JsonToken.EndObject:
+ foreach (KeyValuePair requiredMapping in requiredMappings)
+ {
+ if (!requiredMapping.Value)
+ throw new JsonSerializationException("Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, requiredMapping.Key));
+ }
+ // TODO: move below, change to RemoveAt
+ //DeserializeStack.Remove(context);
return newObject;
default:
throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType);
@@ -772,7 +703,7 @@ namespace Newtonsoft.Json
return false;
}
- private void WriteMemberInfoProperty(JsonWriter writer, object value, MemberMapping memberMapping)
+ private void WriteMemberInfoProperty(JsonWriter writer, object value, JsonMemberMapping memberMapping)
{
MemberInfo member = memberMapping.Member;
string propertyName = memberMapping.MappingName;
@@ -819,7 +750,7 @@ namespace Newtonsoft.Json
TypeConverter converter = TypeDescriptor.GetConverter(objectType);
// use the objectType's TypeConverter if it has one and can convert to a string
- if (converter != null && !(converter is ComponentConverter) && converter.GetType() != typeof(TypeConverter))
+ if (converter != null && !(converter is ComponentConverter) && (converter.GetType() != typeof(TypeConverter) || value is Type))
{
if (converter.CanConvertTo(typeof(string)))
{
@@ -828,7 +759,7 @@ namespace Newtonsoft.Json
}
}
#else
- if (value is Guid)
+ if (value is Guid || value is Type)
{
writer.WriteValue(value.ToString());
return;
@@ -839,9 +770,9 @@ namespace Newtonsoft.Json
writer.WriteStartObject();
- MemberMappingCollection memberMappings = GetMemberMappings(objectType);
+ JsonMemberMappingCollection memberMappings = GetMemberMappings(objectType);
- foreach (MemberMapping memberMapping in memberMappings)
+ foreach (JsonMemberMapping memberMapping in memberMappings)
{
if (!memberMapping.Ignored && memberMapping.Readable)
WriteMemberInfoProperty(writer, value, memberMapping);
@@ -849,7 +780,7 @@ namespace Newtonsoft.Json
writer.WriteEndObject();
- writer.SerializeStack.Remove(value);
+ writer.SerializeStack.RemoveAt(writer.SerializeStack.Count - 1);
}
private void SerializeEnumerable(JsonWriter writer, IEnumerable values)
diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs
index 74f751c1..db67b261 100644
--- a/Src/Newtonsoft.Json/JsonTextReader.cs
+++ b/Src/Newtonsoft.Json/JsonTextReader.cs
@@ -381,12 +381,16 @@ namespace Newtonsoft.Json
private bool ParseProperty()
{
+ char quoteChar;
+
if (ValidIdentifierChar(_currentChar))
{
+ quoteChar = '\0';
ParseUnquotedProperty();
}
else if (_currentChar == '"' || _currentChar == '\'')
{
+ quoteChar = _currentChar;
ParseQuotedProperty(_currentChar);
}
else
@@ -401,6 +405,7 @@ namespace Newtonsoft.Json
}
SetToken(JsonToken.PropertyName, _buffer.ToString());
+ QuoteChar = quoteChar;
_buffer.Position = 0;
return true;
diff --git a/Src/Newtonsoft.Json/JsonValidatingReader.cs b/Src/Newtonsoft.Json/JsonValidatingReader.cs
new file mode 100644
index 00000000..faa2b62e
--- /dev/null
+++ b/Src/Newtonsoft.Json/JsonValidatingReader.cs
@@ -0,0 +1,535 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Schema;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+using System.Text.RegularExpressions;
+
+namespace Newtonsoft.Json
+{
+ public class JsonValidatingReader : JsonReader
+ {
+ private class SchemaScope
+ {
+ private readonly JsonTokenType _tokenType;
+ private readonly JsonSchemaModel _schema;
+ private readonly Dictionary _requiredProperties;
+
+ public string CurrentPropertyName { get; set; }
+ public int ArrayItemCount { get; set; }
+
+ public JsonSchemaModel Schema
+ {
+ get { return _schema; }
+ }
+
+ public Dictionary RequiredProperties
+ {
+ get { return _requiredProperties; }
+ }
+
+ public JsonTokenType TokenType
+ {
+ get { return _tokenType; }
+ }
+
+ public SchemaScope(JsonTokenType tokenType, JsonSchemaModel schema)
+ {
+ _tokenType = tokenType;
+ _schema = schema;
+
+ if (_schema != null && _schema.Properties != null)
+ {
+ _requiredProperties = GetRequiredProperties(_schema).Distinct().ToDictionary(p => p, p => false);
+ }
+ }
+
+ 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));
+ }
+ }
+
+ private readonly JsonReader _reader;
+ private readonly Stack _stack;
+ private JsonSchema _schema;
+ private JsonSchemaModel _model;
+ private SchemaScope _currentScope;
+
+ public event ValidationEventHandler ValidationEventHandler;
+
+ public override object Value
+ {
+ get { return _reader.Value; }
+ }
+
+ public override int Depth
+ {
+ get { return _reader.Depth; }
+ }
+
+ public override char QuoteChar
+ {
+ get { return _reader.QuoteChar; }
+ protected internal set { }
+ }
+
+ public override JsonToken TokenType
+ {
+ get { return _reader.TokenType; }
+ }
+
+ public override Type ValueType
+ {
+ get { return _reader.ValueType; }
+ }
+
+ private void Push(SchemaScope scope)
+ {
+ _stack.Push(scope);
+ _currentScope = scope;
+ }
+
+ private SchemaScope Pop()
+ {
+ SchemaScope poppedScope = _stack.Pop();
+ _currentScope = (_stack.Count != 0)
+ ? _stack.Peek()
+ : null;
+
+ return poppedScope;
+ }
+
+ private JsonSchemaModel CurrentSchema
+ {
+ get { return _currentScope.Schema; }
+ }
+
+ private JsonSchemaModel CurrentMemberSchema
+ {
+ get
+ {
+ if (_currentScope == null)
+ return _model;
+
+ if (_currentScope.Schema == null)
+ return null;
+
+ switch (_currentScope.TokenType)
+ {
+ case JsonTokenType.None:
+ return _currentScope.Schema;
+ case JsonTokenType.Object:
+ if (_currentScope.CurrentPropertyName == null)
+ throw new Exception("CurrentPropertyName has not been set on scope.");
+
+ JsonSchemaModel propertySchema;
+ if (CurrentSchema.Properties.TryGetValue(_currentScope.CurrentPropertyName, out propertySchema))
+ return propertySchema;
+
+ return (CurrentSchema.AllowAdditionalProperties) ? CurrentSchema.AdditionalProperties : null;
+ case JsonTokenType.Array:
+ if (!CollectionUtils.IsNullOrEmpty(CurrentSchema.Items))
+ {
+ if (CurrentSchema.Items.Count == 1)
+ return CurrentSchema.Items[0];
+
+ if (CurrentSchema.Items.Count > (_currentScope.ArrayItemCount - 1))
+ return CurrentSchema.Items[_currentScope.ArrayItemCount - 1];
+ }
+
+ return (CurrentSchema.AllowAdditionalProperties) ? CurrentSchema.AdditionalProperties : null;
+ case JsonTokenType.Constructor:
+ return null;
+ default:
+ throw new ArgumentOutOfRangeException("TokenType", "Unexpected token type: {0}".FormatWith(CultureInfo.InvariantCulture, _currentScope.TokenType));
+ }
+ }
+ }
+
+ private void RaiseError(string message, JsonSchemaModel schema)
+ {
+ OnValidationEvent(new JsonSchemaException(message));
+ }
+
+ private void OnValidationEvent(JsonSchemaException exception)
+ {
+ ValidationEventHandler handler = ValidationEventHandler;
+ if (handler != null)
+ handler(this, new ValidationEventArgs(exception));
+ else
+ throw exception;
+ }
+
+ public JsonValidatingReader(JsonReader reader)
+ {
+ ValidationUtils.ArgumentNotNull(reader, "reader");
+ _reader = reader;
+ _stack = new Stack();
+ }
+
+ public JsonSchema Schema
+ {
+ get { return _schema; }
+ set
+ {
+ if (TokenType != JsonToken.None)
+ throw new Exception("Cannot change schema while validating JSON.");
+
+ _schema = value;
+ _model = null;
+ }
+ }
+
+ public JsonReader Reader
+ {
+ get { return _reader; }
+ }
+
+ private void ValidateInEnumAndNotDisallowed(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ JToken value = new JValue(_reader.Value);
+
+ if (schema.Enum != null)
+ {
+ if (!schema.Enum.Contains(value, new JTokenEqualityComparer()))
+ RaiseError("Value {0} is not defined in enum.".FormatWith(CultureInfo.InvariantCulture, value),
+ schema);
+ }
+
+ JsonSchemaType? currentNodeType = GetCurrentNodeSchemaType();
+ if (currentNodeType != null)
+ {
+ if (JsonSchemaGenerator.HasFlag(schema.Disallow, currentNodeType.Value))
+ RaiseError("Type {0} is disallowed.".FormatWith(CultureInfo.InvariantCulture, currentNodeType), schema);
+ }
+ }
+
+ private JsonSchemaType? GetCurrentNodeSchemaType()
+ {
+ switch (_reader.TokenType)
+ {
+ case JsonToken.StartObject:
+ return JsonSchemaType.Object;
+ case JsonToken.StartArray:
+ return JsonSchemaType.Array;
+ case JsonToken.Integer:
+ return JsonSchemaType.Integer;
+ case JsonToken.Float:
+ return JsonSchemaType.Float;
+ case JsonToken.String:
+ return JsonSchemaType.String;
+ case JsonToken.Boolean:
+ return JsonSchemaType.Boolean;
+ case JsonToken.Null:
+ return JsonSchemaType.Null;
+ default:
+ return null;
+ }
+ }
+
+ public override bool Read()
+ {
+ if (!_reader.Read())
+ return false;
+
+ if (_reader.TokenType == JsonToken.Comment)
+ return true;
+
+ // first time Read has been called. build model
+ if (_model == null)
+ {
+ JsonSchemaModelBuilder builder = new JsonSchemaModelBuilder();
+ _model = builder.Build(_schema);
+ }
+
+ switch (_reader.TokenType)
+ {
+ case JsonToken.StartObject:
+ ProcessValue();
+ JsonSchemaModel objectSchema = (ValidateObject(CurrentMemberSchema))
+ ? CurrentMemberSchema
+ : null;
+ Push(new SchemaScope(JsonTokenType.Object, objectSchema));
+ break;
+ case JsonToken.StartArray:
+ ProcessValue();
+ JsonSchemaModel arraySchema = (ValidateArray(CurrentMemberSchema))
+ ? CurrentMemberSchema
+ : null;
+ Push(new SchemaScope(JsonTokenType.Array, arraySchema));
+ break;
+ case JsonToken.StartConstructor:
+ Push(new SchemaScope(JsonTokenType.Constructor, null));
+ break;
+ case JsonToken.PropertyName:
+ ValidatePropertyName(CurrentSchema);
+ break;
+ case JsonToken.Raw:
+ break;
+ case JsonToken.Integer:
+ ProcessValue();
+ ValidateInteger(CurrentMemberSchema);
+ break;
+ case JsonToken.Float:
+ ProcessValue();
+ ValidateFloat(CurrentMemberSchema);
+ break;
+ case JsonToken.String:
+ ProcessValue();
+ ValidateString(CurrentMemberSchema);
+ break;
+ case JsonToken.Boolean:
+ ProcessValue();
+ ValidateBoolean(CurrentMemberSchema);
+ break;
+ case JsonToken.Null:
+ ProcessValue();
+ ValidateNull(CurrentMemberSchema);
+ break;
+ case JsonToken.Undefined:
+ break;
+ case JsonToken.EndObject:
+ ValidateEndObject(CurrentSchema);
+ Pop();
+ break;
+ case JsonToken.EndArray:
+ ValidateEndArray(CurrentSchema);
+ Pop();
+ break;
+ case JsonToken.EndConstructor:
+ Pop();
+ break;
+ case JsonToken.Date:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+
+ return true;
+ }
+
+ private void ValidateEndObject(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ Dictionary requiredProperties = _currentScope.RequiredProperties;
+
+ if (requiredProperties != null)
+ {
+ List unmatchedRequiredProperties =
+ requiredProperties.Where(kv => !kv.Value).Select(kv => kv.Key).ToList();
+
+ if (unmatchedRequiredProperties.Count > 0)
+ RaiseError("Non-optional properties are missing from object: {0}".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", unmatchedRequiredProperties.ToArray())), schema);
+ }
+ }
+
+ private void ValidateEndArray(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ int arrayItemCount = _currentScope.ArrayItemCount;
+
+ if (schema.MaximumItems != null && arrayItemCount > schema.MaximumItems)
+ RaiseError("Array item count {0} exceeds maximum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, schema.MaximumItems), schema);
+
+ if (schema.MinimumItems != null && arrayItemCount < schema.MinimumItems)
+ RaiseError("Array item count {0} is less than minimum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, schema.MinimumItems), schema);
+ }
+
+ private void ValidateNull(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ if (!TestType(schema, JsonSchemaType.Null))
+ return;
+
+ ValidateInEnumAndNotDisallowed(schema);
+ }
+
+ private void ValidateBoolean(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ if (!TestType(schema, JsonSchemaType.Boolean))
+ return;
+
+ ValidateInEnumAndNotDisallowed(schema);
+ }
+
+ private void ValidateString(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ if (!TestType(schema, JsonSchemaType.String))
+ return;
+
+ ValidateInEnumAndNotDisallowed(schema);
+
+ string value = _reader.Value.ToString();
+
+ if (schema.MaximumLength != null && value.Length > schema.MaximumLength)
+ RaiseError("String '{0}' exceeds maximum length of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.MaximumLength), schema);
+
+ if (schema.MinimumLength != null && value.Length < schema.MinimumLength)
+ RaiseError("String '{0}' is less than minimum length of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.MinimumLength), schema);
+
+ if (schema.Patterns != null)
+ {
+ foreach (string pattern in schema.Patterns)
+ {
+ if (!Regex.IsMatch(value, pattern))
+ RaiseError("String '{0}' does not match regex pattern '{1}'.".FormatWith(CultureInfo.InvariantCulture, value, pattern), schema);
+ }
+ }
+ }
+
+ private void ValidateInteger(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ if (!TestType(schema, JsonSchemaType.Integer))
+ return;
+
+ ValidateInEnumAndNotDisallowed(schema);
+
+ long value = Convert.ToInt64(_reader.Value, CultureInfo.InvariantCulture);
+
+ if (schema.Maximum != null && value > schema.Maximum)
+ RaiseError("Integer {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema);
+
+ if (schema.Minimum != null && value < schema.Minimum)
+ RaiseError("Integer {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema);
+ }
+
+ private void ProcessValue()
+ {
+ if (_currentScope != null && _currentScope.TokenType == JsonTokenType.Array)
+ {
+ _currentScope.ArrayItemCount++;
+
+ if (CurrentSchema != null && CurrentSchema.Items != null && CurrentSchema.Items.Count > 1 && _currentScope.ArrayItemCount >= CurrentSchema.Items.Count)
+ RaiseError("Index {0} has not been defined and schema does not allow additional items.".FormatWith(CultureInfo.InvariantCulture, _currentScope.ArrayItemCount), CurrentSchema);
+ }
+ }
+
+ private void ValidateFloat(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ if (!TestType(schema, JsonSchemaType.Float))
+ return;
+
+ ValidateInEnumAndNotDisallowed(schema);
+
+ double value = Convert.ToDouble(_reader.Value);
+
+ if (schema.Maximum != null && value > schema.Maximum)
+ RaiseError("Float {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Maximum), schema);
+
+ if (schema.Minimum != null && value < schema.Minimum)
+ RaiseError("Float {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Minimum), schema);
+
+ if (schema.MaximumDecimals != null && MathUtils.GetDecimalPlaces(value) > schema.MaximumDecimals)
+ RaiseError("Float {0} exceeds the maximum allowed number decimal places of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.MaximumDecimals), schema);
+ }
+
+ private void ValidatePropertyName(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return;
+
+ string propertyName = Convert.ToString(_reader.Value, CultureInfo.InvariantCulture);
+
+ if (_currentScope.RequiredProperties.ContainsKey(propertyName))
+ _currentScope.RequiredProperties[propertyName] = true;
+
+ if (!schema.Properties.ContainsKey(propertyName))
+ {
+ IList definedProperties = schema.Properties.Select(p => p.Key).ToList();
+
+ if (!schema.AllowAdditionalProperties && !definedProperties.Contains(propertyName))
+ {
+ RaiseError("Property '{0}' has not been defined and schema does not allow additional properties.".FormatWith(CultureInfo.InvariantCulture, propertyName), schema);
+ }
+ }
+
+ _currentScope.CurrentPropertyName = propertyName;
+ }
+
+ private bool ValidateArray(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return true;
+
+ return (TestType(schema, JsonSchemaType.Array));
+ }
+
+ private bool ValidateObject(JsonSchemaModel schema)
+ {
+ if (schema == null)
+ return true;
+
+ return (TestType(schema, JsonSchemaType.Object));
+ }
+
+ private bool TestType(JsonSchemaModel currentSchema, JsonSchemaType currentType)
+ {
+ if (!JsonSchemaGenerator.HasFlag(currentSchema.Type, currentType))
+ {
+ RaiseError("Invalid type. Expected {0} but got {1}.".FormatWith(CultureInfo.InvariantCulture, currentSchema.Type, currentType), currentSchema);
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs
index 2a940e47..888dbadd 100644
--- a/Src/Newtonsoft.Json/JsonWriter.cs
+++ b/Src/Newtonsoft.Json/JsonWriter.cs
@@ -122,9 +122,9 @@ namespace Newtonsoft.Json
private int _top;
private List _stack;
- private List _serializeStack;
private State _currentState;
private Formatting _formatting;
+ private List _serializeStack;
internal List SerializeStack
{
@@ -192,7 +192,7 @@ namespace Newtonsoft.Json
///
public JsonWriter()
{
- _stack = new List(1);
+ _stack = new List(8);
_stack.Add(JsonTokenType.None);
_currentState = State.Start;
_formatting = Formatting.None;
@@ -529,6 +529,9 @@ namespace Newtonsoft.Json
case JsonTokenType.Array:
_currentState = State.Array;
break;
+ case JsonTokenType.Constructor:
+ _currentState = State.Array;
+ break;
case JsonTokenType.None:
_currentState = State.Start;
break;
diff --git a/Src/Newtonsoft.Json/Linq/JArray.cs b/Src/Newtonsoft.Json/Linq/JArray.cs
index 55dfd054..5466efe9 100644
--- a/Src/Newtonsoft.Json/Linq/JArray.cs
+++ b/Src/Newtonsoft.Json/Linq/JArray.cs
@@ -96,7 +96,7 @@ namespace Newtonsoft.Json.Linq
/// Loads an from a .
///
/// A that will be read for the content of the .
- /// A that contains the XML that was read from the specified .
+ /// A that contains the JSON that was read from the specified .
public static JArray Load(JsonReader reader)
{
if (reader.TokenType == JsonToken.None)
@@ -105,14 +105,13 @@ namespace Newtonsoft.Json.Linq
throw new Exception("Error reading JArray from JsonReader.");
}
if (reader.TokenType != JsonToken.StartArray)
- {
- throw new Exception("Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
- }
- else
- {
- if (!reader.Read())
- throw new Exception("Error reading JArray from JsonReader.");
- }
+ throw new Exception(
+ "Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(
+ CultureInfo.InvariantCulture, reader.TokenType));
+
+ if (!reader.Read())
+ throw new Exception("Error reading JArray from JsonReader.");
+
JArray a = new JArray();
a.ReadContentFrom(reader);
@@ -145,7 +144,7 @@ namespace Newtonsoft.Json.Linq
///
/// The object that will be used to create .
/// A with the values of the specified object
- public static JArray FromObject(object o)
+ public static new JArray FromObject(object o)
{
JToken token = FromObjectInternal(o);
diff --git a/Src/Newtonsoft.Json/Linq/JConstructor.cs b/Src/Newtonsoft.Json/Linq/JConstructor.cs
index c381aaea..dba14b85 100644
--- a/Src/Newtonsoft.Json/Linq/JConstructor.cs
+++ b/Src/Newtonsoft.Json/Linq/JConstructor.cs
@@ -160,5 +160,33 @@ namespace Newtonsoft.Json.Linq
{
return _name.GetHashCode() ^ ContentsHashCode();
}
+
+ ///
+ /// Loads an from a .
+ ///
+ /// A that will be read for the content of the .
+ /// A that contains the JSON that was read from the specified .
+ public static JConstructor Load(JsonReader reader)
+ {
+ if (reader.TokenType == JsonToken.None)
+ {
+ if (!reader.Read())
+ throw new Exception("Error reading JConstructor from JsonReader.");
+ }
+
+ if (reader.TokenType != JsonToken.StartConstructor)
+ throw new Exception(
+ "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(
+ CultureInfo.InvariantCulture, reader.TokenType));
+
+ JConstructor c = new JConstructor((string)reader.Value);
+
+ if (!reader.Read())
+ throw new Exception("Error reading JConstructor from JsonReader.");
+
+ c.ReadContentFrom(reader);
+
+ return c;
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs
index 557ffd89..043c6d98 100644
--- a/Src/Newtonsoft.Json/Linq/JContainer.cs
+++ b/Src/Newtonsoft.Json/Linq/JContainer.cs
@@ -26,7 +26,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using Newtonsoft.Json.Utilities;
using System.Collections;
using System.Diagnostics;
@@ -191,22 +190,6 @@ namespace Newtonsoft.Json.Linq
}
}
- internal static JToken FromObjectInternal(object o)
- {
- ValidationUtils.ArgumentNotNull(o, "o");
-
- JsonSerializer jsonSerializer = new JsonSerializer();
-
- JToken token;
- using (JsonTokenWriter jsonWriter = new JsonTokenWriter())
- {
- jsonSerializer.Serialize(jsonWriter, o);
- token = jsonWriter.Token;
- }
-
- return token;
- }
-
internal static JToken GetIndex(JContainer c, object o)
{
return c.Children().ElementAt((int)o);
@@ -387,10 +370,12 @@ namespace Newtonsoft.Json.Linq
do
{
- if (parent is JProperty)
+ if (parent is JProperty && ((JProperty)parent).Value != null)
{
- if (((JProperty)parent).Value != null)
- parent = parent.Parent;
+ if (parent == this)
+ return;
+
+ parent = parent.Parent;
}
switch (r.TokenType)
diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs
index d0fd004d..99315540 100644
--- a/Src/Newtonsoft.Json/Linq/JObject.cs
+++ b/Src/Newtonsoft.Json/Linq/JObject.cs
@@ -181,7 +181,7 @@ namespace Newtonsoft.Json.Linq
/// Loads an from a .
///
/// A that will be read for the content of the .
- /// A that contains the XML that was read from the specified .
+ /// A that contains the JSON that was read from the specified .
public static JObject Load(JsonReader reader)
{
ValidationUtils.ArgumentNotNull(reader, "reader");
@@ -192,14 +192,12 @@ namespace Newtonsoft.Json.Linq
throw new Exception("Error reading JObject from JsonReader.");
}
if (reader.TokenType != JsonToken.StartObject)
- {
- throw new Exception("Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
- }
- else
- {
- if (!reader.Read())
- throw new Exception("Error reading JObject from JsonReader.");
- }
+ throw new Exception(
+ "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(
+ CultureInfo.InvariantCulture, reader.TokenType));
+
+ if (!reader.Read())
+ throw new Exception("Error reading JObject from JsonReader.");
JObject o = new JObject();
o.ReadContentFrom(reader);
@@ -224,7 +222,7 @@ namespace Newtonsoft.Json.Linq
///
/// The object that will be used to create .
/// A with the values of the specified object
- public static JObject FromObject(object o)
+ public static new JObject FromObject(object o)
{
JToken token = FromObjectInternal(o);
diff --git a/Src/Newtonsoft.Json/Linq/JProperty.cs b/Src/Newtonsoft.Json/Linq/JProperty.cs
index 2a26df0c..61c01101 100644
--- a/Src/Newtonsoft.Json/Linq/JProperty.cs
+++ b/Src/Newtonsoft.Json/Linq/JProperty.cs
@@ -54,7 +54,7 @@ namespace Newtonsoft.Json.Linq
/// Gets or sets the property value.
///
/// The property value.
- public JToken Value
+ public new JToken Value
{
[DebuggerStepThrough]
get { return Last; }
@@ -107,13 +107,26 @@ namespace Newtonsoft.Json.Linq
/// Initializes a new instance of the class.
///
/// The property name.
- /// The property value.
- public JProperty(string name, object value)
+ /// The property content.
+ public JProperty(string name, params object[] content)
+ : this(name, (object)content)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The property name.
+ /// The property content.
+ public JProperty(string name, object content)
{
ValidationUtils.ArgumentNotNull(name, "name");
_name = name;
- Value = CreateFromContent(value);
+
+ Value = IsMultiContent(content)
+ ? new JArray(content)
+ : CreateFromContent(content);
}
internal override void ValidateObject(JToken o, JToken previous)
@@ -154,5 +167,32 @@ namespace Newtonsoft.Json.Linq
{
return _name.GetHashCode() ^ ((Value != null) ? Value.GetDeepHashCode() : 0);
}
+
+ ///
+ /// Loads an from a .
+ ///
+ /// A that will be read for the content of the .
+ /// A that contains the JSON that was read from the specified .
+ public static JProperty Load(JsonReader reader)
+ {
+ if (reader.TokenType == JsonToken.None)
+ {
+ if (!reader.Read())
+ throw new Exception("Error reading JProperty from JsonReader.");
+ }
+ if (reader.TokenType != JsonToken.PropertyName)
+ throw new Exception(
+ "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(
+ CultureInfo.InvariantCulture, reader.TokenType));
+
+ JProperty p = new JProperty((string)reader.Value);
+
+ if (!reader.Read())
+ throw new Exception("Error reading JProperty from JsonReader.");
+
+ p.ReadContentFrom(reader);
+
+ return p;
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs
index 7a2b5928..beb7201b 100644
--- a/Src/Newtonsoft.Json/Linq/JToken.cs
+++ b/Src/Newtonsoft.Json/Linq/JToken.cs
@@ -146,7 +146,7 @@ namespace Newtonsoft.Json.Linq
if (_parent == null)
return null;
- JToken parentNext = ((JToken)_parent.Content)._next;
+ JToken parentNext = _parent.Content._next;
JToken parentNextBefore = null;
while (parentNext != this)
{
@@ -736,5 +736,66 @@ namespace Newtonsoft.Json.Linq
{
get { return this[key]; }
}
+
+ public JsonReader CreateReader()
+ {
+ return new JsonTokenReader(this);
+ }
+
+ internal static JToken FromObjectInternal(object o)
+ {
+ ValidationUtils.ArgumentNotNull(o, "o");
+
+ JsonSerializer jsonSerializer = new JsonSerializer();
+
+ JToken token;
+ using (JsonTokenWriter jsonWriter = new JsonTokenWriter())
+ {
+ jsonSerializer.Serialize(jsonWriter, o);
+ token = jsonWriter.Token;
+ }
+
+ return token;
+ }
+
+ ///
+ /// Creates a from an object.
+ ///
+ /// The object that will be used to create .
+ /// A with the value of the specified object
+ public static JToken FromObject(object o)
+ {
+ return FromObjectInternal(o);
+ }
+
+ public static JToken ReadFrom(JsonReader reader)
+ {
+ ValidationUtils.ArgumentNotNull(reader, "reader");
+
+ if (reader.TokenType == JsonToken.None)
+ {
+ if (!reader.Read())
+ throw new Exception("Error reading JToken from JsonReader.");
+ }
+
+ if (reader.TokenType == JsonToken.StartObject)
+ return JObject.Load(reader);
+
+ if (reader.TokenType == JsonToken.StartArray)
+ return JArray.Load(reader);
+
+ if (reader.TokenType == JsonToken.PropertyName)
+ return JProperty.Load(reader);
+
+ if (reader.TokenType == JsonToken.StartConstructor)
+ return JConstructor.Load(reader);
+
+ // hack. change to look at TokenType rather than using value
+ if (!JsonReader.IsStartToken(reader.TokenType))
+ return new JValue(reader.Value);
+
+ // TODO: loading constructor and parameters?
+ throw new Exception("Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+ }
}
}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Linq/JsonTokenReader.cs b/Src/Newtonsoft.Json/Linq/JsonTokenReader.cs
index 31e16438..6cb6bae7 100644
--- a/Src/Newtonsoft.Json/Linq/JsonTokenReader.cs
+++ b/Src/Newtonsoft.Json/Linq/JsonTokenReader.cs
@@ -11,7 +11,7 @@ namespace Newtonsoft.Json.Linq
///
public class JsonTokenReader : JsonReader
{
- private JToken _root;
+ private readonly JToken _root;
private JToken _parent;
private JToken _current;
diff --git a/Src/Newtonsoft.Json/Linq/JsonTokenWriter.cs b/Src/Newtonsoft.Json/Linq/JsonTokenWriter.cs
index a3c86ec1..2ce79379 100644
--- a/Src/Newtonsoft.Json/Linq/JsonTokenWriter.cs
+++ b/Src/Newtonsoft.Json/Linq/JsonTokenWriter.cs
@@ -13,14 +13,22 @@ namespace Newtonsoft.Json.Linq
{
private JContainer _token;
private JContainer _parent;
+ // used when writer is writing single value and the value has no containing parent
+ private JValue _value;
///
/// Gets the token being writen.
///
/// The token being writen.
- public JContainer Token
+ public JToken Token
{
- get { return _token; }
+ get
+ {
+ if (_token != null)
+ return _token;
+
+ return _value;
+ }
}
///
@@ -133,10 +141,17 @@ namespace Newtonsoft.Json.Linq
private void AddValue(JValue value, JsonToken token)
{
- _parent.Add(value);
+ if (_parent != null)
+ {
+ _parent.Add(value);
- if (_parent.Type == JsonTokenType.Property)
- _parent = _parent.Parent;
+ if (_parent.Type == JsonTokenType.Property)
+ _parent = _parent.Parent;
+ }
+ else
+ {
+ _value = value;
+ }
}
#region WriteValue methods
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj
index a4147f96..fe3dc84a 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj
@@ -55,60 +55,83 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj
index 424a3a13..f49c490a 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj
@@ -53,7 +53,10 @@
+
+
+
@@ -70,6 +73,7 @@
+
@@ -86,8 +90,6 @@
-
-
@@ -100,6 +102,9 @@
+
+
+
@@ -107,6 +112,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+