From db51672f600030090afd91bb4ad740a9aeae155c Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 8 Dec 2013 11:33:01 +1300 Subject: [PATCH] -Added DisallowIntegerValues setting to StringEnumConverter --- .../Bson/BsonReaderTests.cs | 89 +++++++++++++++++++ .../Converters/StringEnumConverterTests.cs | 22 +++++ .../Converters/StringEnumConverter.cs | 16 +++- Src/Newtonsoft.Json/JsonReader.cs | 2 +- 4 files changed, 125 insertions(+), 4 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs index 5db43112..af451447 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs @@ -26,6 +26,9 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Reflection; +using System.Runtime.Serialization; +using Newtonsoft.Json.Serialization; #if !(NET20 || NET35 || PORTABLE) using System.Numerics; #endif @@ -1509,5 +1512,91 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual("(hi)", c.Regex.ToString()); Assert.AreEqual(RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase, c.Regex.Options); } + + class Zoo + { + public List Animals { get; set; } + } + + class Animal + { + public Animal(string name) + { + Name = name; + } + + public string Name { get; private set; } + } + + class Dog : Animal + { + public Dog(string name) + : base(name) + { + } + } + + class Cat : Animal + { + public Cat(string name) + : base(name) + { + } + } + + public class MyBinder : DefaultSerializationBinder + { + public bool BindToNameCalled { get; set; } + public bool BindToTypeCalled { get; set; } + + public override void BindToName(Type serializedType, out string assemblyName, out string typeName) + { + BindToNameCalled = true; + base.BindToName(serializedType, out assemblyName, out typeName); + } + + public override Type BindToType(string assemblyName, string typeName) + { + BindToTypeCalled = true; + return base.BindToType(assemblyName, typeName); + } + } + + [Test] + public void TypeNameHandlingAuto() + { + var binder = new MyBinder(); + + var settings = new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Auto, + Binder = binder + }; + + Zoo zoo = new Zoo + { + Animals = new List + { + new Dog("Dog!") + } + }; + + JsonSerializer serializer = JsonSerializer.Create(settings); + + MemoryStream ms = new MemoryStream(); + BsonWriter bsonWriter = new BsonWriter(ms); + serializer.Serialize(bsonWriter, zoo); + + ms.Seek(0, SeekOrigin.Begin); + + var deserialized = serializer.Deserialize(new BsonReader(ms)); + + Assert.AreEqual(1, deserialized.Animals.Count); + Assert.AreEqual("Dog!", deserialized.Animals[0].Name); + Assert.IsTrue(deserialized.Animals[0] is Dog); + + Assert.IsTrue(binder.BindToNameCalled); + Assert.IsTrue(binder.BindToTypeCalled); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Converters/StringEnumConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/StringEnumConverterTests.cs index 2ca5aaab..20a77e78 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/StringEnumConverterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/StringEnumConverterTests.cs @@ -368,6 +368,28 @@ namespace Newtonsoft.Json.Tests.Converters Beta, } + [Test] + public void DeserializeIntegerButNotAllowed() + { + string json = "{ \"Value\" : 123 }"; + + try + { + var serializer = new JsonSerializer(); + serializer.Converters.Add(new StringEnumConverter { DisallowIntegerValues = true }); + serializer.Deserialize(new JsonTextReader(new StringReader(json))); + } + catch (JsonSerializationException ex) + { + Assert.AreEqual("Error converting value 123 to type 'Newtonsoft.Json.Tests.Converters.StringEnumConverterTests+MyEnum'. Path 'Value', line 1, position 15.", ex.Message); + Assert.AreEqual(@"Integer value 123 is not allowed. Path 'Value', line 1, position 15.", ex.InnerException.Message); + + return; + } + + Assert.Fail(); + } + #if !NET20 [Test] public void EnumMemberPlusFlags() diff --git a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs index 93661d19..a12c54b8 100644 --- a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs +++ b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs @@ -28,7 +28,6 @@ using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Runtime.Serialization; -using Newtonsoft.Json.Schema; using Newtonsoft.Json.Utilities; #if NET20 using Newtonsoft.Json.Utilities.LinqBridge; @@ -52,6 +51,12 @@ namespace Newtonsoft.Json.Converters /// true if the written enum text will be camel case; otherwise, false. public bool CamelCaseText { get; set; } + /// + /// Gets or sets a value indicating whether integer values are disallowed. + /// + /// true if integers are disallowed; otherwise, false. + public bool DisallowIntegerValues { get; set; } + /// /// Writes the JSON representation of the object. /// @@ -153,15 +158,20 @@ namespace Newtonsoft.Json.Converters } if (reader.TokenType == JsonToken.Integer) + { + if (DisallowIntegerValues) + throw JsonSerializationException.Create(reader, "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, reader.Value)); + return ConvertUtils.ConvertOrCast(reader.Value, CultureInfo.InvariantCulture, t); + } } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.FormatValueForPrint(reader.Value), objectType), ex); } - - throw JsonSerializationException.Create(reader, "Unexpected token when parsing enum. Expected String or Integer, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); + // we don't actually expect to get here. + throw JsonSerializationException.Create(reader, "Unexpected token {0} when parsing enum.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } private static string ResolvedEnumName(BidirectionalDictionary map, string enumText) diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs index 0a951b50..22ac7c9f 100644 --- a/Src/Newtonsoft.Json/JsonReader.cs +++ b/Src/Newtonsoft.Json/JsonReader.cs @@ -149,7 +149,7 @@ namespace Newtonsoft.Json /// /// Gets or sets a value indicating whether multiple pieces of JSON content can - /// be read from a stream of content without erroring. + /// be read from a continuous stream without erroring. /// /// /// true to support reading multiple pieces of JSON content; otherwise false. The default is false.