diff --git a/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs b/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs index e899b1a0..d2538de9 100644 --- a/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs +++ b/Src/Newtonsoft.Json.Tests/Schema/ExtensionsTests.cs @@ -30,6 +30,11 @@ using System.Text; using NUnit.Framework; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Linq; +using System.IO; +using Newtonsoft.Json.Tests.TestObjects; +#if !SILVERLIGHT +using System.Data; +#endif namespace Newtonsoft.Json.Tests.Schema { @@ -144,5 +149,53 @@ namespace Newtonsoft.Json.Tests.Schema // true } + private void GenerateSchemaAndSerializeFromType(T value) + { + JsonSchemaGenerator generator = new JsonSchemaGenerator(); + generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseAssemblyQualifiedName; + JsonSchema typeSchema = generator.Generate(typeof (T)); + string schema = typeSchema.ToString(); + + string json = JsonConvert.SerializeObject(value, Formatting.Indented); + JToken token = JToken.ReadFrom(new JsonTextReader(new StringReader(json))); + + List errors = new List(); + + token.Validate(typeSchema, (sender, args) => + { + errors.Add(args.Message); + }); + + if (errors.Count > 0) + Assert.Fail("Schema generated for type '{0}' is not valid." + Environment.NewLine + string.Join(Environment.NewLine, errors.ToArray()), typeof(T)); + } + + [Test] + public void GenerateSchemaAndSerializeFromTypeTests() + { + GenerateSchemaAndSerializeFromType(new List { "1", "Two", "III" }); + GenerateSchemaAndSerializeFromType(new List { 1 }); + GenerateSchemaAndSerializeFromType(new Version("1.2.3.4")); + GenerateSchemaAndSerializeFromType(new Store()); + GenerateSchemaAndSerializeFromType(new Person()); + GenerateSchemaAndSerializeFromType(new PersonRaw()); + GenerateSchemaAndSerializeFromType(new CircularReferenceClass() { Name = "I'm required" }); + GenerateSchemaAndSerializeFromType(new CircularReferenceWithIdClass()); + GenerateSchemaAndSerializeFromType(new ClassWithArray()); + GenerateSchemaAndSerializeFromType(new ClassWithGuid()); +#if !NET20 && !PocketPC + GenerateSchemaAndSerializeFromType(new NullableDateTimeTestClass()); +#endif +#if !SILVERLIGHT + GenerateSchemaAndSerializeFromType(new DataSet()); +#endif + GenerateSchemaAndSerializeFromType(new object()); + GenerateSchemaAndSerializeFromType(1); + GenerateSchemaAndSerializeFromType("Hi"); + GenerateSchemaAndSerializeFromType(new DateTime(2000, 12, 29, 23, 59, 0, DateTimeKind.Utc)); + GenerateSchemaAndSerializeFromType(TimeSpan.FromTicks(1000000)); + GenerateSchemaAndSerializeFromType(DBNull.Value); + GenerateSchemaAndSerializeFromType(new JsonPropertyWithHandlingValues()); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs index 47fd0df9..f907f017 100644 --- a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs +++ b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs @@ -59,14 +59,17 @@ namespace Newtonsoft.Json.Tests.Schema ""null"" ], ""items"": { - ""type"": ""string"" + ""type"": [ + ""string"", + ""null"" + ] } } }", json); Dictionary> value = new Dictionary> { - {"HasValue", new List() { "first", "second"}}, + {"HasValue", new List() { "first", "second", null }}, {"NoValue", null} }; @@ -282,7 +285,7 @@ namespace Newtonsoft.Json.Tests.Schema Assert.AreEqual(JsonSchemaType.String | JsonSchemaType.Null, schema.Properties["Name"].Type); Assert.AreEqual("MyExplicitId", schema.Id); - Assert.AreEqual(JsonSchemaType.Object, schema.Properties["Child"].Type); + Assert.AreEqual(JsonSchemaType.Object | JsonSchemaType.Null, schema.Properties["Child"].Type); Assert.AreEqual(schema, schema.Properties["Child"]); } @@ -532,6 +535,90 @@ namespace Newtonsoft.Json.Tests.Schema // should succeed Assert.IsNotNull(jsonSchema); } + + [Test] + public void CircularReferenceWithMixedRequires() + { + JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(); + + jsonSchemaGenerator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName; + JsonSchema jsonSchema = jsonSchemaGenerator.Generate(typeof(CircularReferenceClass)); + string json = jsonSchema.ToString(); + + Assert.AreEqual(@"{ + ""id"": ""Newtonsoft.Json.Tests.TestObjects.CircularReferenceClass"", + ""optional"": true, + ""type"": [ + ""object"", + ""null"" + ], + ""properties"": { + ""Name"": { + ""type"": ""string"" + }, + ""Child"": { + ""$ref"": ""Newtonsoft.Json.Tests.TestObjects.CircularReferenceClass"" + } + } +}", json); + } + + [Test] + public void JsonPropertyWithHandlingValues() + { + JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(); + + jsonSchemaGenerator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName; + JsonSchema jsonSchema = jsonSchemaGenerator.Generate(typeof(JsonPropertyWithHandlingValues)); + string json = jsonSchema.ToString(); + + Assert.AreEqual(@"{ + ""id"": ""Newtonsoft.Json.Tests.TestObjects.JsonPropertyWithHandlingValues"", + ""type"": [ + ""object"", + ""null"" + ], + ""properties"": { + ""DefaultValueHandlingIgnoreProperty"": { + ""optional"": true, + ""type"": [ + ""string"", + ""null"" + ], + ""default"": ""Default!"" + }, + ""DefaultValueHandlingIncludeProperty"": { + ""type"": [ + ""string"", + ""null"" + ], + ""default"": ""Default!"" + }, + ""NullValueHandlingIgnoreProperty"": { + ""optional"": true, + ""type"": [ + ""string"", + ""null"" + ] + }, + ""NullValueHandlingIncludeProperty"": { + ""type"": [ + ""string"", + ""null"" + ] + }, + ""ReferenceLoopHandlingErrorProperty"": { + ""$ref"": ""Newtonsoft.Json.Tests.TestObjects.JsonPropertyWithHandlingValues"" + }, + ""ReferenceLoopHandlingIgnoreProperty"": { + ""$ref"": ""Newtonsoft.Json.Tests.TestObjects.JsonPropertyWithHandlingValues"" + }, + ""ReferenceLoopHandlingSerializeProperty"": { + ""$ref"": ""Newtonsoft.Json.Tests.TestObjects.JsonPropertyWithHandlingValues"" + } + } +}", json); + } } public class DMDSLBase diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index d0f5e7f5..c2da8bbd 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -2546,6 +2546,19 @@ keyword such as type of business."" internal DateTimeOffset _dateTimeOffsetValue; internal Person _personValue; internal Person _nullPersonValue; + internal int? _nullableInt; + internal bool _booleanValue; + internal byte _byteValue; + internal char _charValue; + internal DateTime _dateTimeValue; + internal decimal _decimalValue; + internal short _shortValue; + internal long _longValue; + internal sbyte _sbyteValue; + internal float _floatValue; + internal ushort _ushortValue; + internal uint _uintValue; + internal ulong _ulongValue; public ISerializableTestObject(string stringValue, int intValue, DateTimeOffset dateTimeOffset, Person personValue) { @@ -2553,6 +2566,7 @@ keyword such as type of business."" _intValue = intValue; _dateTimeOffsetValue = dateTimeOffset; _personValue = personValue; + _dateTimeValue = new DateTime(0, DateTimeKind.Utc); } protected ISerializableTestObject(SerializationInfo info, StreamingContext context) @@ -2562,6 +2576,20 @@ keyword such as type of business."" _dateTimeOffsetValue = (DateTimeOffset)info.GetValue("dateTimeOffsetValue", typeof(DateTimeOffset)); _personValue = (Person)info.GetValue("personValue", typeof(Person)); _nullPersonValue = (Person)info.GetValue("nullPersonValue", typeof(Person)); + _nullableInt = (int?)info.GetValue("nullableInt", typeof(int?)); + + _booleanValue = info.GetBoolean("booleanValue"); + _byteValue = info.GetByte("byteValue"); + _charValue = info.GetChar("charValue"); + _dateTimeValue = info.GetDateTime("dateTimeValue"); + _decimalValue = info.GetDecimal("decimalValue"); + _shortValue = info.GetInt16("shortValue"); + _longValue = info.GetInt64("longValue"); + _sbyteValue = info.GetSByte("sbyteValue"); + _floatValue = info.GetSingle("floatValue"); + _ushortValue = info.GetUInt16("ushortValue"); + _uintValue = info.GetUInt32("uintValue"); + _ulongValue = info.GetUInt64("ulongValue"); } public void GetObjectData(SerializationInfo info, StreamingContext context) @@ -2571,6 +2599,20 @@ keyword such as type of business."" info.AddValue("dateTimeOffsetValue", _dateTimeOffsetValue); info.AddValue("personValue", _personValue); info.AddValue("nullPersonValue", _nullPersonValue); + info.AddValue("nullableInt", null); + + info.AddValue("booleanValue", _booleanValue); + info.AddValue("byteValue", _byteValue); + info.AddValue("charValue", _charValue); + info.AddValue("dateTimeValue", _dateTimeValue); + info.AddValue("decimalValue", _decimalValue); + info.AddValue("shortValue", _shortValue); + info.AddValue("longValue", _longValue); + info.AddValue("sbyteValue", _sbyteValue); + info.AddValue("floatValue", _floatValue); + info.AddValue("ushortValue", _ushortValue); + info.AddValue("uintValue", _uintValue); + info.AddValue("ulongValue", _ulongValue); } } @@ -2603,7 +2645,20 @@ keyword such as type of business."" ""BirthDate"": ""\/Date(946688461000)\/"", ""LastModified"": ""\/Date(946688461000)\/"" }, - ""nullPersonValue"": null + ""nullPersonValue"": null, + ""nullableInt"": null, + ""booleanValue"": false, + ""byteValue"": 0, + ""charValue"": ""\u0000"", + ""dateTimeValue"": ""\/Date(-62135596800000)\/"", + ""decimalValue"": 0.0, + ""shortValue"": 0, + ""longValue"": 0, + ""sbyteValue"": 0, + ""floatValue"": 0.0, + ""ushortValue"": 0, + ""uintValue"": 0, + ""ulongValue"": 0 }", json); ISerializableTestObject o2 = JsonConvert.DeserializeObject(json); @@ -2612,6 +2667,7 @@ keyword such as type of business."" Assert.AreEqual(dateTimeOffset, o2._dateTimeOffsetValue); Assert.AreEqual("Name!", o2._personValue.Name); Assert.AreEqual(null, o2._nullPersonValue); + Assert.AreEqual(null, o2._nullableInt); } #endif } diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/CircularReferenceClass.cs b/Src/Newtonsoft.Json.Tests/TestObjects/CircularReferenceClass.cs index 5c313b40..bdb40127 100644 --- a/Src/Newtonsoft.Json.Tests/TestObjects/CircularReferenceClass.cs +++ b/Src/Newtonsoft.Json.Tests/TestObjects/CircularReferenceClass.cs @@ -34,6 +34,7 @@ namespace Newtonsoft.Json.Tests.TestObjects { [JsonProperty(Required = Required.Always)] public string Name { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public CircularReferenceClass Child { get; set; } } -} +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj index a4cbca53..b748d2c7 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Compact.csproj @@ -164,7 +164,7 @@ - + @@ -187,6 +187,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj index d01d2488..4335ec51 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj @@ -183,12 +183,13 @@ - + + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj index 3526ee86..d0f4aaa3 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj @@ -147,7 +147,7 @@ - + @@ -167,6 +167,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj index 6bd17992..f9512fbc 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj @@ -188,7 +188,8 @@ - + + diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index f39102e3..1659d483 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -49,8 +49,21 @@ using System.Security; [assembly: InternalsVisibleTo("Newtonsoft.Json.Tests")] #endif +#else + +#if SILVERLIGHT +[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests.Silverlight, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] +#elif PocketPC +[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests.Compact, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] +#elif NET20 +[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests.Net20, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] +#else +[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] #endif +#endif + + [assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")] diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs index f7a903b4..a78c81e9 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs @@ -155,7 +155,7 @@ namespace Newtonsoft.Json.Schema _resolver = resolver; - return GenerateInternal(type, (!rootSchemaNullable) ? Required.Always : Required.Default); + return GenerateInternal(type, (!rootSchemaNullable) ? Required.Always : Required.Default, false); } private string GetTitle(Type type) @@ -205,7 +205,7 @@ namespace Newtonsoft.Json.Schema } } - private JsonSchema GenerateInternal(Type type, Required valueRequired) + private JsonSchema GenerateInternal(Type type, Required valueRequired, bool optional) { ValidationUtils.ArgumentNotNull(type, "type"); @@ -216,7 +216,16 @@ namespace Newtonsoft.Json.Schema { JsonSchema resolvedSchema = _resolver.GetSchema(resolvedId); if (resolvedSchema != null) + { + // resolved schema is not null but referencing member allows nulls + // change resolved schema to allow nulls. hacky but what are ya gonna do? + if (valueRequired != Required.Always && !HasFlag(resolvedSchema.Type, JsonSchemaType.Null)) + resolvedSchema.Type |= JsonSchemaType.Null; + if (optional && resolvedSchema.Optional != true) + resolvedSchema.Optional = true; + return resolvedSchema; + } } // test for unresolved circular reference @@ -230,12 +239,18 @@ namespace Newtonsoft.Json.Schema if (explicitId != null) CurrentSchema.Id = explicitId; + if (optional) + CurrentSchema.Optional = true; CurrentSchema.Title = GetTitle(type); CurrentSchema.Description = GetDescription(type); JsonContract contract = ContractResolver.ResolveContract(type); - - if (contract is JsonDictionaryContract) + if (contract.Converter != null || contract.InternalConverter != null) + { + // todo: Add GetSchema to JsonConverter and use here? + CurrentSchema.Type = JsonSchemaType.Any; + } + else if (contract is JsonDictionaryContract) { CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired); @@ -248,7 +263,7 @@ namespace Newtonsoft.Json.Schema // can be converted to a string if (typeof (IConvertible).IsAssignableFrom(keyType)) { - CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default); + CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, false); } } } @@ -259,13 +274,13 @@ namespace Newtonsoft.Json.Schema CurrentSchema.Id = GetTypeId(type, false); JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetJsonContainerAttribute(type) as JsonArrayAttribute; - bool allowNullItem = (arrayAttribute != null) ? arrayAttribute.AllowNullItems : false; + bool allowNullItem = (arrayAttribute != null) ? arrayAttribute.AllowNullItems : true; Type collectionItemType = ReflectionUtils.GetCollectionItemType(type); if (collectionItemType != null) { CurrentSchema.Items = new List(); - CurrentSchema.Items.Add(GenerateInternal(collectionItemType, (!allowNullItem) ? Required.Always : Required.Default)); + CurrentSchema.Items.Add(GenerateInternal(collectionItemType, (!allowNullItem) ? Required.Always : Required.Default, false)); } } else if (contract is JsonPrimitiveContract) @@ -309,6 +324,10 @@ namespace Newtonsoft.Json.Schema CurrentSchema.Type = schemaType; } + else if (contract is JsonLinqContract) + { + CurrentSchema.Type = JsonSchemaType.Any; + } else { throw new Exception("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract)); @@ -332,7 +351,10 @@ namespace Newtonsoft.Json.Schema { if (!property.Ignored) { - JsonSchema propertySchema = GenerateInternal(property.PropertyType, property.Required); + bool optional = property.NullValueHandling == NullValueHandling.Ignore || + property.DefaultValueHandling == DefaultValueHandling.Ignore; + + JsonSchema propertySchema = GenerateInternal(property.PropertyType, property.Required, optional); if (property.DefaultValue != null) propertySchema.Default = JToken.FromObject(property.DefaultValue); @@ -377,10 +399,7 @@ namespace Newtonsoft.Json.Schema { case TypeCode.Empty: case TypeCode.Object: - if (ConvertUtils.CanConvertType(type, typeof(string), false)) - return schemaType | JsonSchemaType.String; - - return schemaType | JsonSchemaType.Object; + return schemaType | JsonSchemaType.String; case TypeCode.DBNull: return schemaType | JsonSchemaType.Null; case TypeCode.Boolean: diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 95c1f117..5df4fa31 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -323,7 +323,11 @@ namespace Newtonsoft.Json.Serialization ConstructorInfo constructorInfo = objectType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new [] {typeof (SerializationInfo), typeof (StreamingContext)}, null); if (constructorInfo != null) - contract.ISerializableCreator = LateBoundDelegateFactory.CreateMethodHandler(constructorInfo); + { + MethodCaller methodCaller = LateBoundDelegateFactory.CreateMethodCall(constructorInfo); + + contract.ISerializableCreator = (args => methodCaller(null, args)); + } return contract; } diff --git a/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs b/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs index 9f45fdfb..d7ddc162 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs @@ -41,7 +41,7 @@ namespace Newtonsoft.Json.Serialization private bool _isCollectionItemTypeNullableType; private Type _genericCollectionDefinitionType; private Type _genericWrapperType; - private MemberHandler _genericWrapperCreator; + private MethodCaller _genericWrapperCreator; /// /// Initializes a new instance of the class. @@ -66,10 +66,6 @@ namespace Newtonsoft.Json.Serialization { CreatedType = ReflectionUtils.MakeGenericType(typeof(List<>), CollectionItemType); } - else - { - CreatedType = UnderlyingType; - } } internal IWrappedCollection CreateWrapper(object list) @@ -83,7 +79,7 @@ namespace Newtonsoft.Json.Serialization ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType }); #if !PocketPC && !SILVERLIGHT - _genericWrapperCreator = LateBoundDelegateFactory.CreateMethodHandler(genericWrapperConstructor); + _genericWrapperCreator = LateBoundDelegateFactory.CreateMethodCall(genericWrapperConstructor); #else _genericWrapperCreator = (target, args) => genericWrapperConstructor.Invoke(new[] { args[0] }); #endif diff --git a/Src/Newtonsoft.Json/Serialization/JsonContract.cs b/Src/Newtonsoft.Json/Serialization/JsonContract.cs index 482b3486..634d3ca2 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonContract.cs @@ -147,6 +147,7 @@ namespace Newtonsoft.Json.Serialization ValidationUtils.ArgumentNotNull(underlyingType, "underlyingType"); UnderlyingType = underlyingType; + CreatedType = underlyingType; } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs b/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs index 04b2b9d1..cc8fc570 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs @@ -41,7 +41,7 @@ namespace Newtonsoft.Json.Serialization private readonly Type _genericCollectionDefinitionType; private Type _genericWrapperType; - private MemberHandler _genericWrapperCreator; + private MethodCaller _genericWrapperCreator; /// /// Initializes a new instance of the class. @@ -69,10 +69,6 @@ namespace Newtonsoft.Json.Serialization { CreatedType = ReflectionUtils.MakeGenericType(typeof(Dictionary<,>), keyType, valueType); } - else - { - CreatedType = underlyingType; - } } internal IWrappedDictionary CreateWrapper(object dictionary) @@ -86,7 +82,7 @@ namespace Newtonsoft.Json.Serialization ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType }); #if !PocketPC && !SILVERLIGHT - _genericWrapperCreator = LateBoundDelegateFactory.CreateMethodHandler(genericWrapperConstructor); + _genericWrapperCreator = LateBoundDelegateFactory.CreateMethodCall(genericWrapperConstructor); #else _genericWrapperCreator = (target, args) => genericWrapperConstructor.Invoke(new[] { args[0] }); #endif diff --git a/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs b/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs index aa12accc..f44373ae 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs @@ -37,7 +37,7 @@ namespace Newtonsoft.Json.Serialization /// public class JsonISerializableContract : JsonContract { - public MemberHandler ISerializableCreator { get; set; } + public ObjectConstructor ISerializableCreator { get; set; } /// /// Initializes a new instance of the class. @@ -46,7 +46,6 @@ namespace Newtonsoft.Json.Serialization public JsonISerializableContract(Type underlyingType) : base(underlyingType) { - CreatedType = underlyingType; } } } diff --git a/Src/Newtonsoft.Json/Serialization/JsonLinqContract.cs b/Src/Newtonsoft.Json/Serialization/JsonLinqContract.cs index 795ff9f0..bc3526ff 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonLinqContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonLinqContract.cs @@ -17,7 +17,6 @@ namespace Newtonsoft.Json.Serialization public JsonLinqContract(Type underlyingType) : base(underlyingType) { - CreatedType = underlyingType; } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs b/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs index 343f5cf8..bb078963 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs @@ -59,7 +59,6 @@ namespace Newtonsoft.Json.Serialization : base(underlyingType) { Properties = new JsonPropertyCollection(this); - CreatedType = underlyingType; } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs b/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs index a0e04bc3..60bc83ad 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs @@ -39,7 +39,6 @@ namespace Newtonsoft.Json.Serialization public JsonPrimitiveContract(Type underlyingType) : base(underlyingType) { - CreatedType = underlyingType; } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 33672f8f..f456fbb9 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -650,7 +650,7 @@ namespace Newtonsoft.Json.Serialization if (contract.ISerializableCreator == null) throw new JsonSerializationException("ISerializable type '{0}' does not have a valid constructor.".FormatWith(CultureInfo.InvariantCulture, objectType)); - object createdObject = contract.ISerializableCreator(null, new object[] { serializationInfo, Serializer.Context }); + object createdObject = contract.ISerializableCreator(new object[] { serializationInfo, Serializer.Context }); if (id != null) Serializer.ReferenceResolver.AddReference(id, createdObject); diff --git a/Src/Newtonsoft.Json/Serialization/JsonStringContract.cs b/Src/Newtonsoft.Json/Serialization/JsonStringContract.cs index bf1bda81..1f3f47cd 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonStringContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonStringContract.cs @@ -42,7 +42,6 @@ namespace Newtonsoft.Json.Serialization public JsonStringContract(Type underlyingType) : base(underlyingType) { - CreatedType = underlyingType; } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/MemberHandler.cs b/Src/Newtonsoft.Json/Serialization/MemberHandler.cs deleted file mode 100644 index eb66dc2f..00000000 --- a/Src/Newtonsoft.Json/Serialization/MemberHandler.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Newtonsoft.Json.Serialization -{ - public delegate object MemberHandler(T target, params object[] args); -} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/ObjectConstructor.cs b/Src/Newtonsoft.Json/Serialization/ObjectConstructor.cs new file mode 100644 index 00000000..90d43d43 --- /dev/null +++ b/Src/Newtonsoft.Json/Serialization/ObjectConstructor.cs @@ -0,0 +1,29 @@ +#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.Serialization +{ + public delegate object ObjectConstructor(params object[] args); +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/LateBoundDelegateFactory.cs b/Src/Newtonsoft.Json/Utilities/LateBoundDelegateFactory.cs index 7ea3a340..d3d1dc12 100644 --- a/Src/Newtonsoft.Json/Utilities/LateBoundDelegateFactory.cs +++ b/Src/Newtonsoft.Json/Utilities/LateBoundDelegateFactory.cs @@ -31,7 +31,6 @@ using System.Reflection; using System.Reflection.Emit; using System.Text; using System.Globalization; -using Newtonsoft.Json.Serialization; namespace Newtonsoft.Json.Utilities { @@ -72,7 +71,7 @@ namespace Newtonsoft.Json.Utilities throw new Exception("Could not create setter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo)); } - public static MemberHandler CreateMethodHandler(MethodBase method) + public static MethodCaller CreateMethodCall(MethodBase method) { DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType); ILGenerator generator = dynamicMethod.GetILGenerator(); @@ -121,7 +120,7 @@ namespace Newtonsoft.Json.Utilities generator.Emit(OpCodes.Ret); - return (MemberHandler)dynamicMethod.CreateDelegate(typeof(MemberHandler)); + return (MethodCaller)dynamicMethod.CreateDelegate(typeof(MethodCaller)); } diff --git a/Src/Newtonsoft.Json/Utilities/MethodCaller.cs b/Src/Newtonsoft.Json/Utilities/MethodCaller.cs new file mode 100644 index 00000000..e588d126 --- /dev/null +++ b/Src/Newtonsoft.Json/Utilities/MethodCaller.cs @@ -0,0 +1,29 @@ +#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.Utilities +{ + internal delegate object MethodCaller(T target, params object[] args); +} \ No newline at end of file