如何在.NET中自定义JSON枚举的反序列化?

use*_*046 8 c# wcf json xsd datacontractserializer

我有以下示例C#代码,它们使用svcutils.exe应用程序从xsd自动生成.

    [DataContract]
    public enum Foo
    {
        [EnumMember(Value = "bar")]
        Bar = 1,

        [EnumMember(Value = "baz")]
        Baz = 2
    }

    [DataContract]
    public class UNameIt
    {
        [DataMember(Name = "id")]
        public long Id { get; private set; }

        [DataMember(Name = "name")]
        public string Name { get; private set; }

        [DataMember(Name = "foo")]
        public Foo Foo { get; private set; }
    }
Run Code Online (Sandbox Code Playgroud)

以下是单元测试,尝试将示例JSON文档反序列化为UNameIt类.

    [TestClass]
    public class JsonSerializer_Fixture
    {
        public const string JsonData = @"{ ""id"":123456,
                                           ""name"":""John Doe"",
                                           ""foo"":""Bar""}";

        [TestMethod]
        public void DataObjectSimpleParseTest()
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(UNameIt));

            MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(JsonData));
            UNameIt dataObject = serializer.ReadObject(ms) as UNameIt;

            Assert.IsNotNull(dataObject);
            Assert.AreEqual(123456, dataObject.Id);
            Assert.AreEqual(Foo.Baz, dataObject.Foo);
        }
    }
Run Code Online (Sandbox Code Playgroud)

不幸的是,测试失败的原因如下:

System.Runtime.Serialization.SerializationException:反序列化MyNamespace.Units.UNameIt类型的对象时出错."Bar"值无法解析为"Int64"类型.

如果我更新我的JSON字符串以将Enum的字符串说明符替换为整数,则测试将通过,例如

public const string JsonData = @"{ ""id"":123456,
                                   ""name"":""John Doe"",
                                    ""foo"":""1""}";
Run Code Online (Sandbox Code Playgroud)

我没有更改提供的JSON的灵活性,所以我必须弄清楚如何在序列化时转换字符串Enum表示.理想情况下,我想在不必更改自动生成类的情况下为此提供帮助,因为一旦我重新生成类,我就会失去我的更改.

我想知道是否可以将DataContractJsonSerializer扩展为自定义句柄枚举?或者也许有更好的方法来做到这一点?

Enr*_*lio 6

此行为是设计使然.以下是MSDN上Enumerations和JSON段落的引用:

枚举成员值在JSON中被视为数字,这与在数据协定中处理它们的方式不同,它们作为成员名称包含在内.

此外,DataContractJsonSerializer将自动序列化所有枚举,因此实际上忽略了EnumMemberAttribute.

有关解决方法,请查看SO上的答案.