如何在。net中定制JSON枚举的反序列化?

时间:2022-10-02 17:18:17

I have the following sample C# code that is auto-genereated from an xsd using the svcutils.exe application.

我有以下示例c#代码,它是使用svcutils从xsd自动生成的。exe程序。

    [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; }
    }

The following is a unit test that attempts to deserialise a sample JSON document to the UNameIt class.

下面是一个单元测试,它试图将一个示例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);
        }
    }

Unfortunately, the test fails giving the following reason:

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

System.Runtime.Serialization.SerializationException: There was an error deserializing the object of type MyNamespace.Units.UNameIt. The value 'Bar' cannot be parsed as the type 'Int64'.

System.Runtime.Serialization。SerializationException:在反序列化名称空间. unit. unameit类型的对象时发生了错误。值“Bar”不能被解析为“Int64”类型。

The test will pass if I update my JSON string to replace the string specifier for the Enum to an integer e.g.

如果我更新JSON字符串以将枚举的字符串指示符替换为整数,则测试将通过。

public const string JsonData = @"{ ""id"":123456,
                                   ""name"":""John Doe"",
                                    ""foo"":""1""}";

I do not have the flexibility to the change the supplied JSON so I have to figure out how to convert the string Enum representation perhaps on serialisation. Ideally, I would like to facilitate this without having to change my autogenerate class because once I re-generate the class I would loose my changes.

我没有灵活地更改所提供的JSON,因此我必须弄清楚如何将string Enum表示转换为序列化。理想情况下,我希望在不需要更改自动生成类的情况下促进这一点,因为一旦我重新生成类,我就会失去我的更改。

I am wondering if it would be possible to extend the DataContractJsonSerializer to custom handle Enumerations? Or perhaps there is better way to do this?

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

2 个解决方案

#1


6  

This behavior is by design. Here's a quote from the Enumerations and JSON paragraph on MSDN:

这种行为是故意的。以下是MSDN上的枚举和JSON段落:

Enumeration member values are treated as numbers in JSON, which is different from how they are treated in data contracts, where they are included as member names.

枚举成员值被视为JSON中的数字,这与在数据契约中处理它们的方式不同,它们被作为成员名称包含在其中。

Moreover the DataContractJsonSerializer will automatically serialize all enumerations, so the EnumMemberAttribute is actually ignored.

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

For a workaround, take a look at this answer on SO.

为了解决这个问题,看看这个答案。

#2


0  

This is work :

这是工作:

var ret = new JavaScriptSerializer().Deserialize<tblGridProjects>(retApi.Item2);

But you can't use datamembers attributes, so can't rename properties. You must set the name of the property like Json sended.

但是不能使用datambers属性,所以不能重命名属性。您必须设置属性的名称,如Json sended。

#1


6  

This behavior is by design. Here's a quote from the Enumerations and JSON paragraph on MSDN:

这种行为是故意的。以下是MSDN上的枚举和JSON段落:

Enumeration member values are treated as numbers in JSON, which is different from how they are treated in data contracts, where they are included as member names.

枚举成员值被视为JSON中的数字,这与在数据契约中处理它们的方式不同,它们被作为成员名称包含在其中。

Moreover the DataContractJsonSerializer will automatically serialize all enumerations, so the EnumMemberAttribute is actually ignored.

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

For a workaround, take a look at this answer on SO.

为了解决这个问题,看看这个答案。

#2


0  

This is work :

这是工作:

var ret = new JavaScriptSerializer().Deserialize<tblGridProjects>(retApi.Item2);

But you can't use datamembers attributes, so can't rename properties. You must set the name of the property like Json sended.

但是不能使用datambers属性,所以不能重命名属性。您必须设置属性的名称,如Json sended。