Проблема десериализации с помощью DataContractJsonSerializer - PullRequest
22 голосов
/ 27 февраля 2009

У меня есть следующий фрагмент JSON:

[{
    "name": "numToRetrieve",
    "value": "3",
    "label": "Number of items to retrieve:",
    "items": {
        "1": "1",
        "3": "3",
        "5": "5"
    },
    "rules": {
        "range": "1-2"
    }
},
{
    "name": "showFoo",
    "value": "on",
    "label": "Show foo?"
},
{
    "name": "title",
    "value": "Foo",
    "label": "Foo:"
}]

Версия все в одну строку (подходит для строкового литерала):

[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}]

В приведенном выше примере name, value и label являются обязательными, но items и rules являются необязательными.

Вот класс, в который я пытаюсь десериализоваться:

using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace foofoo
{
    [DataContract]
    public sealed class FooDef
    {
        [DataMember(Name = "name", IsRequired = true)]
        public string Name { get; set; }

        [DataMember(Name = "value", IsRequired = true)]
        public string Value { get; set; }

        [DataMember(Name = "label", IsRequired = true)]
        public string Label { get; set; }

        [DataMember(Name = "items", IsRequired = false)]
        public Dictionary<string, string> Items { get; set; }

        [DataMember(Name = "rules", IsRequired = false)]
        public Dictionary<string, string> Rules { get; set; }
    }
}

Вот код, который я использую для десериализации:

var json = new DataContractJsonSerializer(typeof(List<FooDef>));
var bar = "[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}]";
var stream = new MemoryStream(Encoding.UTF8.GetBytes(bar));
var foo = json.ReadObject(stream);
stream.Close();

Все идет достаточно хорошо, за исключением того, что items и rules пусты для первого прохода FooDef. Я попробовал все под солнцем, чтобы попытаться заполнить их: пользовательские классы, NameValueCollection, KeyValuePair<string, string>, List обоих последних и все остальные коллекции, которые, казалось, применимы. [EDIT: я забыл попробовать Hashtable, который казался очевидным кандидатом. Не сработало.]

Проблема, на мой взгляд, заключается в том, что ключевой элемент под items и rules является открытым. То есть это не всегда будет называться range или 3. Любой совет или идеи?

Ответы [ 2 ]

22 голосов
/ 01 марта 2009

ИМХО, нет способа десериализовать предоставленную вами строку JSON в класс .NET с использованием DataContractJsonSerializer.

Проблема заключается в том, что DataContractJsonSerializer сериализует словари. Вы можете использовать альтернативный сериализатор, такой как Json.NET (который я настоятельно рекомендую) или JavaScriptSerializer (я думаю, что он устарел в пользу DataContractJsonSerializer, но он будет работать для вашего сценария).

Вы также можете прочитать эти ранты .

Документация: Сериализация коллекций - Json.NET

7 голосов
/ 25 июня 2010

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/071f73bb-e141-4a68-ae61-05635382934f

Проверьте эту статью - она ​​решила мою проблему почти идеально. Мне пришлось изменить их тип объекта [] на строку, но я использую только строки: пары типа ключ / значение типа строка, поэтому никаких проблем нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...