Сериализовать словарь как массив (пар ключей)
Json.Net обычно сериализует Dictionary
в коллекцию;
"MyDict": { "Apples": { "Taste": 1341181398, "Title": "Granny Smith", }, "Oranges": { "Taste": 9999999999, "Title": "Coxes Pippin", }, }
Это здорово. И, глядя на SO, похоже, это то, чего хотят большинство людей. Однако в этом конкретном случае я хочу сериализовать между моим Dictionary
и форматом Array;
"MyDict": [ "k": "Apples", "v": { "Taste": 1341181398, "Title": "Granny Smith", } }, "k:": "Oranges", "v:": { "Taste": 9999999999, "Title": "Coxes Pippin", } }, ]
Есть ли простой способ сделать это с помощью моего существующего типа поля? Есть ли атрибут, который я могу аннотировать, например?
- Дессериализация данных JSON на C # с использованием JSON.NET
- Объединение двух массивов Json.NET путем конкатенации содержащихся элементов
- Как убедиться, что строка действительна JSON с использованием JSON.NET
- JSON.Net Обнаружен собственный цикл привязки
- json.net: указать конвертер для ключей словаря
- JSON.Net: принудительная сериализация всех частных полей и всех полей в подclassах
- Deserialize json с известными и неизвестными полями
- Интерфейсы для десериализации в JSON.NET
- C # WCF REST. Как вы используете сериализатор JSON.Net вместо стандартного DataContractSerializer?
- Строка Parse Json в C #
- Разбор большого json-файла в .NET.
- Разбор JSON в C #
- Разбор JSON с использованием Json.net
Другой способ добиться этого – использовать пользовательский ContractResolver
. Таким образом, вам не нужно подclassифицировать Dictionary
и применять преобразование при каждом сериализации, как это предлагается в других ответах.
Следующий резольвер приведет к сериализации ALL словарей как массива объектов с свойствами «Key» и «Value»:
class DictionaryAsArrayResolver : DefaultContractResolver { protected override JsonContract CreateContract(Type objectType) { if (objectType.GetInterfaces().Any(i => i == typeof(IDictionary) || (i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>)))) { return base.CreateArrayContract(objectType); } return base.CreateContract(objectType); } }
Чтобы использовать резольвер, добавьте его в свои JsonSerializerSettings
, а затем передайте настройки JsonConvert.SerializeObject()
следующим образом:
JsonSerializerSettings settings = new JsonSerializerSettings(); settings.ContractResolver = new DictionaryAsArrayResolver(); string json = JsonConvert.SerializeObject(obj, settings);
Вот рабочая демонстрация .
О, оказывается, это так же просто, как я надеялся. Мой Dictionary
уже подclassифицирован, и я обнаружил, что могу его аннотировать с помощью [JsonArrayAttribute]
. Это дает мне именно тот формат, который мне нужен;
"MyDict": [ { "Key": "Apples", "Value": { "Taste": 1341181398, "Title": "Granny Smith", } }, { "Key:": "Oranges", "Value:": { "Taste": 9999999999, "Title": "Coxes Pippin", } }, ]
В этом примере я воспользуюсь изречением:
var myDict = new Dictionary() { {"a","123"}, {"b","234"}, {"c","345"} };
который сериализует (с Newtonsoft.Json.JsonConvert.SerializeObject(myDict)
):
{"a":"123","b":"234","c":"345"}
Вы можете сделать преобразование с помощью LINQ для создания анонимного объекта и сериализовать это:
var myDictTransformed = from key in myDict.Keys select new { k = key, v = myDict[key] };
Или вы можете использовать реальный объект
class MyDictEntry { public string k { get; set; } public string v { get; set; } }
и либо выше, либо альтернативный синтаксис LINQ:
var myDictTransformed = myDict.Keys.AsEnumerable() .Select(key => new MyDictEntry{ k = key, v = myDict[key] });
В любом случае, это сериализуется для:
[ {"k":"a", "v":"123"}, {"k":"b", "v":"234"}, {"k":"c", "v":"345"} ]
Ссылка .NET Fiddle: https://dotnetfiddle.net/LhisVW
Самое простое решение, которое я нашел, – это преобразовать Dictionary
в List
. Затем JSON.NET преобразует ваш List
в массив объектов с формой { Key: 'keyname', Value: 'value' }
. Это хорошо работает, если вы принимаете требуемое изменение модели и не хотите подclassифицировать Dictionary
.
Ответ gregmac был полезен, но не совсем сработал. Следующее – та же идея … без каламбуров.
var dictionaryTransformed = dictionary.Select(item => item.Key).Select(i => new {Key = i, Value = dictionary[i] });
или, конечно же,
var dictionaryTransformed = dictionary.Select(item => new {item.Key, Value = dictionary[item.Key] });
Затем к json
var json = (new JavaScriptSerializer()).Serialize( new { Container = dictionaryTransformed.ToArray() } )