#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.Runtime.Serialization; using System.Text; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; #if DNXCORE50 using Xunit; using Test = Xunit.FactAttribute; using Assert = Newtonsoft.Json.Tests.XUnitAssert; #else using NUnit.Framework; #endif using Newtonsoft.Json.Tests.TestObjects; namespace Newtonsoft.Json.Tests.Converters { [TestFixture] public class StringEnumConverterTests : TestFixtureBase { public class EnumClass { public StoreColor StoreColor { get; set; } public StoreColor? NullableStoreColor1 { get; set; } public StoreColor? NullableStoreColor2 { get; set; } } public class EnumContainer { public T Enum { get; set; } } [Flags] public enum FlagsTestEnum { Default = 0, First = 1, Second = 2 } public enum NegativeEnum { Negative = -1, Zero = 0, Positive = 1 } [Flags] public enum NegativeFlagsEnum { NegativeFour = -4, NegativeTwo = -2, NegativeOne = -1, Zero = 0, One = 1, Two = 2, Four = 4 } #if !NET20 public enum NamedEnum { [EnumMember(Value = "@first")] First, [EnumMember(Value = "@second")] Second, Third } public enum NamedEnumDuplicate { [EnumMember(Value = "Third")] First, [EnumMember(Value = "@second")] Second, Third } public enum NamedEnumWithComma { [EnumMember(Value = "@first")] First, [EnumMember(Value = "@second")] Second, [EnumMember(Value = ",third")] Third, [EnumMember(Value = ",")] JustComma } #endif public class NegativeEnumClass { public NegativeEnum Value1 { get; set; } public NegativeEnum Value2 { get; set; } } public class NegativeFlagsEnumClass { public NegativeFlagsEnum Value1 { get; set; } public NegativeFlagsEnum Value2 { get; set; } } [JsonConverter(typeof(StringEnumConverter), true)] public enum CamelCaseEnumObsolete { This, Is, CamelCase } [JsonConverter(typeof(StringEnumConverter), typeof(CamelCaseNamingStrategy))] public enum CamelCaseEnumNew { This, Is, CamelCase } [JsonConverter(typeof(StringEnumConverter), typeof(SnakeCaseNamingStrategy))] public enum SnakeCaseEnumNew { This, Is, SnakeCase } [JsonConverter(typeof(StringEnumConverter), typeof(CamelCaseNamingStrategy), new object[0], false)] public enum NotAllowIntegerValuesEnum { Foo = 0, Bar = 1 } [JsonConverter(typeof(StringEnumConverter), typeof(CamelCaseNamingStrategy))] public enum AllowIntegerValuesEnum { Foo = 0, Bar = 1 } [JsonConverter(typeof(StringEnumConverter), typeof(CamelCaseNamingStrategy), null)] public enum NullArgumentInAttribute { Foo = 0, Bar = 1 } [Test] public void Serialize_CamelCaseFromAttribute_Obsolete() { string json = JsonConvert.SerializeObject(CamelCaseEnumObsolete.CamelCase); Assert.AreEqual(@"""camelCase""", json); } [Test] public void NamingStrategyAndCamelCaseText() { StringEnumConverter converter = new StringEnumConverter(); Assert.IsNull(converter.NamingStrategy); #pragma warning disable CS0618 // Type or member is obsolete converter.CamelCaseText = true; #pragma warning restore CS0618 // Type or member is obsolete Assert.IsNotNull(converter.NamingStrategy); Assert.AreEqual(typeof(CamelCaseNamingStrategy), converter.NamingStrategy.GetType()); var camelCaseInstance = converter.NamingStrategy; #pragma warning disable CS0618 // Type or member is obsolete converter.CamelCaseText = true; #pragma warning restore CS0618 // Type or member is obsolete Assert.AreEqual(camelCaseInstance, converter.NamingStrategy); converter.NamingStrategy = null; #pragma warning disable CS0618 // Type or member is obsolete Assert.IsFalse(converter.CamelCaseText); #pragma warning restore CS0618 // Type or member is obsolete converter.NamingStrategy = new CamelCaseNamingStrategy(); #pragma warning disable CS0618 // Type or member is obsolete Assert.IsTrue(converter.CamelCaseText); #pragma warning restore CS0618 // Type or member is obsolete converter.NamingStrategy = new SnakeCaseNamingStrategy(); #pragma warning disable CS0618 // Type or member is obsolete Assert.IsFalse(converter.CamelCaseText); #pragma warning restore CS0618 // Type or member is obsolete #pragma warning disable CS0618 // Type or member is obsolete converter.CamelCaseText = false; #pragma warning restore CS0618 // Type or member is obsolete Assert.IsNotNull(converter.NamingStrategy); Assert.AreEqual(typeof(SnakeCaseNamingStrategy), converter.NamingStrategy.GetType()); } [Test] public void StringEnumConverter_CamelCaseTextCtor() { #pragma warning disable CS0618 // Type or member is obsolete StringEnumConverter converter = new StringEnumConverter(true); #pragma warning restore CS0618 // Type or member is obsolete Assert.IsNotNull(converter.NamingStrategy); Assert.AreEqual(typeof(CamelCaseNamingStrategy), converter.NamingStrategy.GetType()); Assert.AreEqual(true, converter.AllowIntegerValues); } [Test] public void StringEnumConverter_NamingStrategyTypeCtor() { StringEnumConverter converter = new StringEnumConverter(typeof(CamelCaseNamingStrategy), new object[] { true, true, true }, false); Assert.IsNotNull(converter.NamingStrategy); Assert.AreEqual(typeof(CamelCaseNamingStrategy), converter.NamingStrategy.GetType()); Assert.AreEqual(false, converter.AllowIntegerValues); Assert.AreEqual(true, converter.NamingStrategy.OverrideSpecifiedNames); Assert.AreEqual(true, converter.NamingStrategy.ProcessDictionaryKeys); Assert.AreEqual(true, converter.NamingStrategy.ProcessExtensionDataNames); } [Test] public void StringEnumConverter_NamingStrategyTypeCtor_Null() { ExceptionAssert.Throws( () => new StringEnumConverter(null), @"Value cannot be null. Parameter name: namingStrategyType", "Value cannot be null. (Parameter 'namingStrategyType')"); } [Test] public void StringEnumConverter_NamingStrategyTypeWithArgsCtor_Null() { ExceptionAssert.Throws( () => new StringEnumConverter(null, new object[] { true, true, true }, false), @"Value cannot be null. Parameter name: namingStrategyType", "Value cannot be null. (Parameter 'namingStrategyType')"); } [Test] public void Deserialize_CamelCaseFromAttribute_Obsolete() { CamelCaseEnumObsolete e = JsonConvert.DeserializeObject(@"""camelCase"""); Assert.AreEqual(CamelCaseEnumObsolete.CamelCase, e); } [Test] public void Serialize_CamelCaseFromAttribute() { string json = JsonConvert.SerializeObject(CamelCaseEnumNew.CamelCase); Assert.AreEqual(@"""camelCase""", json); } [Test] public void Deserialize_CamelCaseFromAttribute() { CamelCaseEnumNew e = JsonConvert.DeserializeObject(@"""camelCase"""); Assert.AreEqual(CamelCaseEnumNew.CamelCase, e); } [Test] public void Serialize_SnakeCaseFromAttribute() { string json = JsonConvert.SerializeObject(SnakeCaseEnumNew.SnakeCase); Assert.AreEqual(@"""snake_case""", json); } [Test] public void Deserialize_SnakeCaseFromAttribute() { SnakeCaseEnumNew e = JsonConvert.DeserializeObject(@"""snake_case"""); Assert.AreEqual(SnakeCaseEnumNew.SnakeCase, e); } [Test] public void Deserialize_NotAllowIntegerValuesFromAttribute() { ExceptionAssert.Throws(() => { NotAllowIntegerValuesEnum e = JsonConvert.DeserializeObject(@"""9"""); }); } [Test] public void CannotPassNullArgumentToConverter() { var ex = ExceptionAssert.Throws(() => { JsonConvert.DeserializeObject(@"""9"""); }); Assert.AreEqual("Cannot pass a null parameter to the constructor.", ex.InnerException.Message); } [Test] public void Deserialize_AllowIntegerValuesAttribute() { AllowIntegerValuesEnum e = JsonConvert.DeserializeObject(@"""9"""); Assert.AreEqual(9, (int)e); } #if !NET20 [Test] public void NamedEnumDuplicateTest() { ExceptionAssert.Throws(() => { EnumContainer c = new EnumContainer { Enum = NamedEnumDuplicate.First }; JsonConvert.SerializeObject(c, Formatting.Indented, new StringEnumConverter()); }, "Enum name 'Third' already exists on enum 'NamedEnumDuplicate'."); } [Test] public void SerializeNameEnumTest() { EnumContainer c = new EnumContainer { Enum = NamedEnum.First }; string json = JsonConvert.SerializeObject(c, Formatting.Indented, new StringEnumConverter()); StringAssert.AreEqual(@"{ ""Enum"": ""@first"" }", json); c = new EnumContainer { Enum = NamedEnum.Third }; json = JsonConvert.SerializeObject(c, Formatting.Indented, new StringEnumConverter()); StringAssert.AreEqual(@"{ ""Enum"": ""Third"" }", json); } [Test] public void NamedEnumCommaTest() { EnumContainer c = new EnumContainer { Enum = NamedEnumWithComma.Third }; string json = JsonConvert.SerializeObject(c, Formatting.Indented, new StringEnumConverter()); StringAssert.AreEqual(@"{ ""Enum"": "",third"" }", json); EnumContainer c2 = JsonConvert.DeserializeObject>(json, new StringEnumConverter()); Assert.AreEqual(NamedEnumWithComma.Third, c2.Enum); } [Test] public void NamedEnumCommaTest2() { EnumContainer c = new EnumContainer { Enum = NamedEnumWithComma.JustComma }; string json = JsonConvert.SerializeObject(c, Formatting.Indented, new StringEnumConverter()); StringAssert.AreEqual(@"{ ""Enum"": "","" }", json); EnumContainer c2 = JsonConvert.DeserializeObject>(json, new StringEnumConverter()); Assert.AreEqual(NamedEnumWithComma.JustComma, c2.Enum); } [Test] public void NamedEnumCommaCaseInsensitiveTest() { EnumContainer c2 = JsonConvert.DeserializeObject>(@"{""Enum"":"",THIRD""}", new StringEnumConverter()); Assert.AreEqual(NamedEnumWithComma.Third, c2.Enum); } [Test] public void DeserializeNameEnumTest() { string json = @"{ ""Enum"": ""@first"" }"; EnumContainer c = JsonConvert.DeserializeObject>(json, new StringEnumConverter()); Assert.AreEqual(NamedEnum.First, c.Enum); json = @"{ ""Enum"": ""Third"" }"; c = JsonConvert.DeserializeObject>(json, new StringEnumConverter()); Assert.AreEqual(NamedEnum.Third, c.Enum); } #endif [Test] public void SerializeEnumClass() { EnumClass enumClass = new EnumClass() { StoreColor = StoreColor.Red, NullableStoreColor1 = StoreColor.White, NullableStoreColor2 = null }; string json = JsonConvert.SerializeObject(enumClass, Formatting.Indented, new StringEnumConverter()); StringAssert.AreEqual(@"{ ""StoreColor"": ""Red"", ""NullableStoreColor1"": ""White"", ""NullableStoreColor2"": null }", json); } [Test] public void SerializeEnumClassWithCamelCase() { EnumClass enumClass = new EnumClass() { StoreColor = StoreColor.Red, NullableStoreColor1 = StoreColor.DarkGoldenrod, NullableStoreColor2 = null }; #pragma warning disable CS0618 // Type or member is obsolete string json = JsonConvert.SerializeObject(enumClass, Formatting.Indented, new StringEnumConverter { CamelCaseText = true }); #pragma warning restore CS0618 // Type or member is obsolete StringAssert.AreEqual(@"{ ""StoreColor"": ""red"", ""NullableStoreColor1"": ""darkGoldenrod"", ""NullableStoreColor2"": null }", json); } [Test] public void SerializeEnumClassUndefined() { EnumClass enumClass = new EnumClass() { StoreColor = (StoreColor)1000, NullableStoreColor1 = (StoreColor)1000, NullableStoreColor2 = null }; string json = JsonConvert.SerializeObject(enumClass, Formatting.Indented, new StringEnumConverter()); StringAssert.AreEqual(@"{ ""StoreColor"": 1000, ""NullableStoreColor1"": 1000, ""NullableStoreColor2"": null }", json); } [Test] public void SerializeFlagEnum() { EnumClass enumClass = new EnumClass() { StoreColor = StoreColor.Red | StoreColor.White, NullableStoreColor1 = StoreColor.White & StoreColor.Yellow, NullableStoreColor2 = StoreColor.Red | StoreColor.White | StoreColor.Black }; string json = JsonConvert.SerializeObject(enumClass, Formatting.Indented, new StringEnumConverter()); StringAssert.AreEqual(@"{ ""StoreColor"": ""Red, White"", ""NullableStoreColor1"": 0, ""NullableStoreColor2"": ""Black, Red, White"" }", json); } [Test] public void SerializeNegativeFlagsEnum() { NegativeFlagsEnumClass negativeEnumClass = new NegativeFlagsEnumClass(); negativeEnumClass.Value1 = NegativeFlagsEnum.NegativeFour | NegativeFlagsEnum.NegativeTwo; negativeEnumClass.Value2 = NegativeFlagsEnum.Two | NegativeFlagsEnum.Four; string json = JsonConvert.SerializeObject(negativeEnumClass, Formatting.Indented, new StringEnumConverter()); StringAssert.AreEqual(@"{ ""Value1"": ""NegativeTwo"", ""Value2"": ""Two, Four"" }", json); } [Test] public void DeserializeNegativeFlagsEnum() { string json = @"{ ""Value1"": ""NegativeFour,NegativeTwo"", ""Value2"": ""NegativeFour,Four"" }"; NegativeFlagsEnumClass negativeEnumClass = JsonConvert.DeserializeObject(json, new StringEnumConverter()); Assert.AreEqual(NegativeFlagsEnum.NegativeFour | NegativeFlagsEnum.NegativeTwo, negativeEnumClass.Value1); Assert.AreEqual(NegativeFlagsEnum.NegativeFour | NegativeFlagsEnum.Four, negativeEnumClass.Value2); } [Test] public void SerializeNegativeEnum() { NegativeEnumClass negativeEnumClass = new NegativeEnumClass() { Value1 = NegativeEnum.Negative, Value2 = (NegativeEnum)int.MinValue }; string json = JsonConvert.SerializeObject(negativeEnumClass, Formatting.Indented, new StringEnumConverter()); StringAssert.AreEqual(@"{ ""Value1"": ""Negative"", ""Value2"": -2147483648 }", json); } [Test] public void DeserializeNegativeEnum() { string json = @"{ ""Value1"": ""Negative"", ""Value2"": -2147483648 }"; NegativeEnumClass negativeEnumClass = JsonConvert.DeserializeObject(json, new StringEnumConverter()); Assert.AreEqual(NegativeEnum.Negative, negativeEnumClass.Value1); Assert.AreEqual((NegativeEnum)int.MinValue, negativeEnumClass.Value2); } [Test] public void DeserializeFlagEnum() { string json = @"{ ""StoreColor"": ""Red, White"", ""NullableStoreColor1"": 0, ""NullableStoreColor2"": ""black, Red, White"" }"; EnumClass enumClass = JsonConvert.DeserializeObject(json, new StringEnumConverter()); Assert.AreEqual(StoreColor.Red | StoreColor.White, enumClass.StoreColor); Assert.AreEqual((StoreColor)0, enumClass.NullableStoreColor1); Assert.AreEqual(StoreColor.Red | StoreColor.White | StoreColor.Black, enumClass.NullableStoreColor2); } [Test] public void DeserializeEnumClass() { string json = @"{ ""StoreColor"": ""Red"", ""NullableStoreColor1"": ""White"", ""NullableStoreColor2"": null }"; EnumClass enumClass = JsonConvert.DeserializeObject(json, new StringEnumConverter()); Assert.AreEqual(StoreColor.Red, enumClass.StoreColor); Assert.AreEqual(StoreColor.White, enumClass.NullableStoreColor1); Assert.AreEqual(null, enumClass.NullableStoreColor2); } [Test] public void DeserializeEnumClassUndefined() { string json = @"{ ""StoreColor"": 1000, ""NullableStoreColor1"": 1000, ""NullableStoreColor2"": null }"; EnumClass enumClass = JsonConvert.DeserializeObject(json, new StringEnumConverter()); Assert.AreEqual((StoreColor)1000, enumClass.StoreColor); Assert.AreEqual((StoreColor)1000, enumClass.NullableStoreColor1); Assert.AreEqual(null, enumClass.NullableStoreColor2); } [Test] public void CamelCaseTextFlagEnumSerialization() { EnumContainer c = new EnumContainer { Enum = FlagsTestEnum.First | FlagsTestEnum.Second }; #pragma warning disable CS0618 // Type or member is obsolete string json = JsonConvert.SerializeObject(c, Formatting.Indented, new StringEnumConverter { CamelCaseText = true }); #pragma warning restore CS0618 // Type or member is obsolete StringAssert.AreEqual(@"{ ""Enum"": ""first, second"" }", json); } [Test] public void CamelCaseTextFlagEnumDeserialization() { string json = @"{ ""Enum"": ""first, second"" }"; #pragma warning disable CS0618 // Type or member is obsolete EnumContainer c = JsonConvert.DeserializeObject>(json, new StringEnumConverter { CamelCaseText = true }); #pragma warning restore CS0618 // Type or member is obsolete Assert.AreEqual(FlagsTestEnum.First | FlagsTestEnum.Second, c.Enum); } [Test] public void DeserializeEmptyStringIntoNullable() { string json = @"{ ""StoreColor"": ""Red"", ""NullableStoreColor1"": ""White"", ""NullableStoreColor2"": """" }"; EnumClass c = JsonConvert.DeserializeObject(json, new StringEnumConverter()); Assert.IsNull(c.NullableStoreColor2); } [Test] public void DeserializeInvalidString() { string json = "{ \"Value\" : \"Three\" }"; ExceptionAssert.Throws(() => { var serializer = new JsonSerializer(); serializer.Converters.Add(new StringEnumConverter()); serializer.Deserialize(new JsonTextReader(new StringReader(json))); }, @"Error converting value ""Three"" to type 'Newtonsoft.Json.Tests.Converters.StringEnumConverterTests+MyEnum'. Path 'Value', line 1, position 19."); } public class Bucket { public MyEnum Value; } public enum MyEnum { Alpha, Beta, } [Test] public void DeserializeIntegerButNotAllowed() { string json = "{ \"Value\" : 123 }"; try { var serializer = new JsonSerializer(); serializer.Converters.Add(new StringEnumConverter { AllowIntegerValues = false }); 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() { List lfoo = new List { Foo.Bat | Foo.SerializeAsBaz, Foo.FooBar, Foo.Bat, Foo.SerializeAsBaz, Foo.FooBar | Foo.SerializeAsBaz, (Foo)int.MaxValue }; #pragma warning disable CS0618 // Type or member is obsolete string json1 = JsonConvert.SerializeObject(lfoo, Formatting.Indented, new StringEnumConverter { CamelCaseText = true }); #pragma warning restore CS0618 // Type or member is obsolete StringAssert.AreEqual(@"[ ""Bat, baz"", ""foo_bar"", ""Bat"", ""baz"", ""foo_bar, baz"", 2147483647 ]", json1); IList foos = JsonConvert.DeserializeObject>(json1); Assert.AreEqual(6, foos.Count); Assert.AreEqual(Foo.Bat | Foo.SerializeAsBaz, foos[0]); Assert.AreEqual(Foo.FooBar, foos[1]); Assert.AreEqual(Foo.Bat, foos[2]); Assert.AreEqual(Foo.SerializeAsBaz, foos[3]); Assert.AreEqual(Foo.FooBar | Foo.SerializeAsBaz, foos[4]); Assert.AreEqual((Foo)int.MaxValue, foos[5]); List lbar = new List() { Bar.FooBar, Bar.Bat, Bar.SerializeAsBaz }; #pragma warning disable CS0618 // Type or member is obsolete string json2 = JsonConvert.SerializeObject(lbar, Formatting.Indented, new StringEnumConverter { CamelCaseText = true }); #pragma warning restore CS0618 // Type or member is obsolete StringAssert.AreEqual(@"[ ""foo_bar"", ""Bat"", ""baz"" ]", json2); IList bars = JsonConvert.DeserializeObject>(json2); Assert.AreEqual(3, bars.Count); Assert.AreEqual(Bar.FooBar, bars[0]); Assert.AreEqual(Bar.Bat, bars[1]); Assert.AreEqual(Bar.SerializeAsBaz, bars[2]); } [Test] public void DuplicateNameEnumTest() { ExceptionAssert.Throws( () => JsonConvert.DeserializeObject("'foo_bar'", new StringEnumConverter()), @"Error converting value ""foo_bar"" to type 'Newtonsoft.Json.Tests.Converters.DuplicateNameEnum'. Path '', line 1, position 9."); } // Define other methods and classes here [Flags] [JsonConverter(typeof(StringEnumConverter))] private enum Foo { [EnumMember(Value = "foo_bar")] FooBar = 0x01, Bat = 0x02, [EnumMember(Value = "baz")] SerializeAsBaz = 0x4, } [JsonConverter(typeof(StringEnumConverter))] private enum Bar { [EnumMember(Value = "foo_bar")] FooBar, Bat, [EnumMember(Value = "baz")] SerializeAsBaz } [Test] public void DataContractSerializerDuplicateNameEnumTest() { MemoryStream ms = new MemoryStream(); var s = new DataContractSerializer(typeof(DuplicateEnumNameTestClass)); ExceptionAssert.Throws(() => { s.WriteObject(ms, new DuplicateEnumNameTestClass { Value = DuplicateNameEnum.foo_bar, Value2 = DuplicateNameEnum2.foo_bar_NOT_USED }); string xml = @" foo_bar foo_bar "; var o = (DuplicateEnumNameTestClass)s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(xml))); Assert.AreEqual(DuplicateNameEnum.foo_bar, o.Value); Assert.AreEqual(DuplicateNameEnum2.FooBar, o.Value2); }, "Type 'Newtonsoft.Json.Tests.Converters.DuplicateNameEnum' contains two members 'foo_bar' 'and 'FooBar' with the same name 'foo_bar'. Multiple members with the same name in one type are not supported. Consider changing one of the member names using EnumMemberAttribute attribute."); } [Test] public void EnumMemberWithNumbers() { StringEnumConverter converter = new StringEnumConverter(); NumberNamesEnum e = JsonConvert.DeserializeObject("\"1\"", converter); Assert.AreEqual(NumberNamesEnum.second, e); e = JsonConvert.DeserializeObject("\"2\"", converter); Assert.AreEqual(NumberNamesEnum.first, e); e = JsonConvert.DeserializeObject("\"3\"", converter); Assert.AreEqual(NumberNamesEnum.third, e); e = JsonConvert.DeserializeObject("\"-4\"", converter); Assert.AreEqual(NumberNamesEnum.fourth, e); } [Test] public void EnumMemberWithNumbers_NoIntegerValues() { StringEnumConverter converter = new StringEnumConverter { AllowIntegerValues = false }; NumberNamesEnum e = JsonConvert.DeserializeObject("\"1\"", converter); Assert.AreEqual(NumberNamesEnum.second, e); e = JsonConvert.DeserializeObject("\"2\"", converter); Assert.AreEqual(NumberNamesEnum.first, e); e = JsonConvert.DeserializeObject("\"3\"", converter); Assert.AreEqual(NumberNamesEnum.third, e); e = JsonConvert.DeserializeObject("\"-4\"", converter); Assert.AreEqual(NumberNamesEnum.fourth, e); } #endif [Test] public void AllowIntegerValueAndStringNumber() { JsonSerializationException ex = ExceptionAssert.Throws(() => { JsonConvert.DeserializeObject("\"1\"", new StringEnumConverter { AllowIntegerValues = false }); }); Assert.AreEqual("Integer string '1' is not allowed.", ex.InnerException.Message); } [Test] public void AllowIntegerValueAndNegativeStringNumber() { JsonSerializationException ex = ExceptionAssert.Throws(() => { JsonConvert.DeserializeObject("\"-1\"", new StringEnumConverter { AllowIntegerValues = false }); }); Assert.AreEqual("Integer string '-1' is not allowed.", ex.InnerException.Message); } [Test] public void AllowIntegerValueAndPositiveStringNumber() { JsonSerializationException ex = ExceptionAssert.Throws(() => { JsonConvert.DeserializeObject("\"+1\"", new StringEnumConverter { AllowIntegerValues = false }); }); Assert.AreEqual("Integer string '+1' is not allowed.", ex.InnerException.Message); } [Test] public void AllowIntegerValueAndDash() { JsonSerializationException ex = ExceptionAssert.Throws(() => { JsonConvert.DeserializeObject("\"-\"", new StringEnumConverter { AllowIntegerValues = false }); }); Assert.AreEqual("Requested value '-' was not found.", ex.InnerException.Message); } [Test] public void AllowIntegerValueAndNonNamedValue() { ExceptionAssert.Throws(() => { JsonConvert.SerializeObject((StoreColor)999, new StringEnumConverter { AllowIntegerValues = false }); }, "Integer value 999 is not allowed. Path ''."); } public enum EnumWithDifferentCases { M, m } [Test] public void SerializeEnumWithDifferentCases() { string json = JsonConvert.SerializeObject(EnumWithDifferentCases.M, new StringEnumConverter()); Assert.AreEqual(@"""M""", json); json = JsonConvert.SerializeObject(EnumWithDifferentCases.m, new StringEnumConverter()); Assert.AreEqual(@"""m""", json); } [Test] public void DeserializeEnumWithDifferentCases() { EnumWithDifferentCases e = JsonConvert.DeserializeObject(@"""M""", new StringEnumConverter()); Assert.AreEqual(EnumWithDifferentCases.M, e); e = JsonConvert.DeserializeObject(@"""m""", new StringEnumConverter()); Assert.AreEqual(EnumWithDifferentCases.m, e); } #if !NET20 [JsonConverter(typeof(StringEnumConverter))] public enum EnumMemberDoesNotMatchName { [EnumMember(Value = "first_value")] First } [Test] public void DeserializeEnumCaseIncensitive_ByEnumMemberValue_UpperCase() { var e = JsonConvert.DeserializeObject(@"""FIRST_VALUE""", new StringEnumConverter()); Assert.AreEqual(EnumMemberDoesNotMatchName.First, e); } [Test] public void DeserializeEnumCaseIncensitive_ByEnumMemberValue_MixedCase() { var e = JsonConvert.DeserializeObject(@"""First_Value""", new StringEnumConverter()); Assert.AreEqual(EnumMemberDoesNotMatchName.First, e); } [Test] public void DeserializeEnumCaseIncensitive_ByName_LowerCase() { var e = JsonConvert.DeserializeObject(@"""first""", new StringEnumConverter()); Assert.AreEqual(EnumMemberDoesNotMatchName.First, e); } [Test] public void DeserializeEnumCaseIncensitive_ByName_UperCase() { var e = JsonConvert.DeserializeObject(@"""FIRST""", new StringEnumConverter()); Assert.AreEqual(EnumMemberDoesNotMatchName.First, e); } [Test] public void DeserializeEnumCaseIncensitive_FromAttribute() { var e = JsonConvert.DeserializeObject(@"""FIRST_VALUE"""); Assert.AreEqual(EnumMemberDoesNotMatchName.First, e); } [JsonConverter(typeof(StringEnumConverter))] public enum EnumMemberWithDiffrentCases { [EnumMember(Value = "first_value")] First, [EnumMember(Value = "second_value")] first } [Test] public void DeserializeEnumMemberWithDifferentCasing_ByEnumMemberValue_First() { var e = JsonConvert.DeserializeObject(@"""first_value""", new StringEnumConverter()); Assert.AreEqual(EnumMemberWithDiffrentCases.First, e); } [Test] public void DeserializeEnumMemberWithDifferentCasing_ByEnumMemberValue_Second() { var e = JsonConvert.DeserializeObject(@"""second_value""", new StringEnumConverter()); Assert.AreEqual(EnumMemberWithDiffrentCases.first, e); } [DataContract(Name = "DateFormats")] public enum EnumMemberWithDifferentCases { [EnumMember(Value = "M")] Month, [EnumMember(Value = "m")] Minute } [Test] public void SerializeEnumMemberWithDifferentCases() { string json = JsonConvert.SerializeObject(EnumMemberWithDifferentCases.Month, new StringEnumConverter()); Assert.AreEqual(@"""M""", json); json = JsonConvert.SerializeObject(EnumMemberWithDifferentCases.Minute, new StringEnumConverter()); Assert.AreEqual(@"""m""", json); } [Test] public void DeserializeEnumMemberWithDifferentCases() { EnumMemberWithDifferentCases e = JsonConvert.DeserializeObject(@"""M""", new StringEnumConverter()); Assert.AreEqual(EnumMemberWithDifferentCases.Month, e); e = JsonConvert.DeserializeObject(@"""m""", new StringEnumConverter()); Assert.AreEqual(EnumMemberWithDifferentCases.Minute, e); } #endif } #if !NET20 [DataContract] public class DuplicateEnumNameTestClass { [DataMember] public DuplicateNameEnum Value { get; set; } [DataMember] public DuplicateNameEnum2 Value2 { get; set; } } [DataContract] public enum NumberNamesEnum { [EnumMember(Value = "2")] first, [EnumMember(Value = "1")] second, [EnumMember(Value = "3")] third, [EnumMember(Value = "-4")] fourth } [DataContract] public enum DuplicateNameEnum { [EnumMember] first = 0, [EnumMember] foo_bar = 1, [EnumMember(Value = "foo_bar")] FooBar = 2, [EnumMember] foo_bar_NOT_USED = 3 } [DataContract] public enum DuplicateNameEnum2 { [EnumMember] first = 0, [EnumMember(Value = "foo_bar")] FooBar = 1, [EnumMember] foo_bar = 2, [EnumMember(Value = "TEST")] foo_bar_NOT_USED = 3 } #endif }