diff --git a/Src/Newtonsoft.Json.Tests/Converters/StringEnumConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/StringEnumConverterTests.cs index 4e8e21f9..dea31862 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/StringEnumConverterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/StringEnumConverterTests.cs @@ -573,7 +573,54 @@ namespace Newtonsoft.Json.Tests.Converters 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); + } + + [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); + } #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); + } } #if !NET20 @@ -587,6 +634,17 @@ namespace Newtonsoft.Json.Tests.Converters public DuplicateNameEnum2 Value2 { get; set; } } + [DataContract] + public enum NumberNamesEnum + { + [EnumMember(Value = "2")] + first, + [EnumMember(Value = "1")] + second, + [EnumMember(Value = "3")] + third + } + [DataContract] public enum DuplicateNameEnum { diff --git a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs index a22ee1e5..b9db34b1 100644 --- a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs +++ b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs @@ -1,4 +1,5 @@ #region License + // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -21,6 +22,7 @@ // 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; @@ -134,7 +136,8 @@ namespace Newtonsoft.Json.Converters if (reader.TokenType == JsonToken.String) { string enumText = reader.Value.ToString(); - return EnumUtils.ParseEnumName(enumText, isNullable, t); + + return EnumUtils.ParseEnumName(enumText, isNullable, !AllowIntegerValues, t); } if (reader.TokenType == JsonToken.Integer) diff --git a/Src/Newtonsoft.Json/Utilities/EnumUtils.cs b/Src/Newtonsoft.Json/Utilities/EnumUtils.cs index 94515751..c361a8c7 100644 --- a/Src/Newtonsoft.Json/Utilities/EnumUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/EnumUtils.cs @@ -190,7 +190,7 @@ namespace Newtonsoft.Json.Utilities return values; } - public static object ParseEnumName(string enumText, bool isNullable, Type t) + public static object ParseEnumName(string enumText, bool isNullable, bool disallowValue, Type t) { if (enumText == string.Empty && isNullable) { @@ -222,6 +222,24 @@ namespace Newtonsoft.Json.Utilities else { finalEnumText = enumText; + + if (disallowValue) + { + bool isNumber = true; + for (int i = 0; i < finalEnumText.Length; i++) + { + if (!char.IsNumber(finalEnumText[i])) + { + isNumber = false; + break; + } + } + + if (isNumber) + { + throw new FormatException("Integer string '{0}' is not allowed.".FormatWith(CultureInfo.InvariantCulture, enumText)); + } + } } return Enum.Parse(t, finalEnumText, true);