Как настроить десериализацию перечисления JSON в .NET? - PullRequest
8 голосов
/ 25 января 2012

У меня есть следующий пример кода C #, который автоматически генерируется из xsd с помощью приложения svcutils.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; }
    }

Ниже приведен модульный тест, который пытается десериализовать образец документа 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);
        }
    }

К сожалению, тест не пройден по следующей причине:

System.Runtime.Serialization.SerializationException: произошла ошибка десериализации объекта типа MyNamespace.Units.UNameIt,Значение 'Bar' не может быть проанализировано как тип 'Int64'.

Тест пройдет, если я обновлю свою строку JSON, чтобы заменить спецификатор строки для Enum на целое число, например

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

У меня нет гибкости для изменения поставляемого JSON, поэтому я должен выяснить, как преобразовать строковое представление Enum, возможно, при сериализации.В идеале, я хотел бы облегчить это, не меняя свой класс для автоматического создания, потому что, как только я заново сгенерирую класс, я потеряю свои изменения.

Мне интересно, можно ли было бы расширить DataContractJsonSerializer для пользовательской обработки перечислений?Или, может быть, есть лучший способ сделать это?

Ответы [ 2 ]

6 голосов
/ 25 января 2012

Это поведение по проекту . Вот цитата из параграфа Enumerations и JSON на MSDN :

Значения членов перечисления обрабатываются как числа в JSON, который отличается от того, как они рассматриваются в данных контрактах, где они находятся включены как имена членов.

Кроме того, DataContractJsonSerializer автоматически сериализует все перечисления, поэтому EnumMemberAttribute фактически игнорируется.

Для обходного пути , посмотрите на этот ответ на SO .

0 голосов
/ 05 ноября 2015

Это работа:

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

Но вы не можете использовать атрибуты камер данных, поэтому не можете переименовывать свойства.Вы должны установить имя свойства как отправлено Json.

...