Использование JSON.NET для доступа к атрибутам JSON для создания словаря C#

Я хочу без особых хлопот преобразовать то, что в конечном счете является словарем JSON, в словарь C#.
Может, я ошибаюсь, используя здесь библиотеку JSON.NET? Класс JArray не хочет давать мне ничего для доступа к атрибуту (только значение), т.е. он сообщает мне значение, но никогда не "ключ".
Я не могу поверить, что никто другой не найдет это ограничение, поэтому предполагаю, что я что-то упускаю. Моя запутанная попытка такова:

Учитывая этот json:

{
 "appSettings" : [
    {"rows": "5"},
    {"columns" : "7"}
  ]
}

Я хотел бы выбрать это в словарь следующим образом:

var dict = jsonObject["appSettings"].Select(s => new 
{
    key = s.Name,    // wish this property existed
    value = s.Value  // wish this property existed
}).ToDictionary(s => s.key, s => s.value);

Это мой UnitTest:

[Test]
public void CanLoadJsonAppSettings()
{
var json = @"
    ""{appSettings"" : [ 
      {""ViewRows"" : ""1""},
      {""ViewColumns"" : ""2""}
    ]}";
    var dict = CreateJsonDictionary(json);
    Assert.That(dict.Count, Is.EqualTo(2));
}

public CreateJsonDictionary(string jsonText)
{
  var jsonObject = JObject.Parse(jsonText);

  return jsonObject["appSettings"].Select(s => new 
  { 
    key = s.Name,
    value = s.Value
  }).ToDictionary(s => s.key, s => s.value);
}

EDIT: благодаря @jim мы стали немного ближе. Для полноты я задокументирую немного неловкий шаг, который мне потребовался, чтобы добраться до нужного мне объекта:

Мне пришлось изменить свой JSON. Вместо использования массива (как в приведенном выше коде) я использовал более простой/настоящий словарь:

var json = @"
{ 
  ""appSettings"" : { 
    ""ViewRows""    : ""1"",
    ""ViewColumns"" : ""2""
    }
}";

Затем мне пришлось разобрать, получить JSON JObject, затем преобразовать обратно в строку, а затем десериализовать:

var jo = JObject.Parse(jsonText);
var appSettings = jo["appSettings"];
var appSettings = JsonConvert.DeserializeObject<Dictionary<string, string>>(appSettings.ToString());

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

EDIT2: мне все еще нужно было решить исходную проблему, описанную выше, преобразовав массив JSON в словарь. Как только мой JSON будет исправлен, чтобы содержать правильные пары имя/значение:

"connectionStrings": [
{"name" : "string1", "value" : "value1"},
{"name" : "string2", "value" :"value2"},
]

Это код, который решил эту проблему (но это очень похоже на мою первоначальную попытку):

var jsonObj = JObject.Parse(jsonText);
var conStrings = jsonObj.Properties().Select(s => 
  new {
  key = s.Name,
  value = s.Value.ToString()
}).ToDictionary(s => s.key, s => s.value);

И это работает, только если у вас нет других массивов.


person PandaWood    schedule 31.01.2011    source источник


Ответы (4)


Панда,

Дословно от самого Джеймса Ньютона Кинга на SO аналогичный вопрос:

// Json.NET does this...

string json = @"{""key1"":""value1"",""key2"":""value2""}";
Dictionary<string, string> values 
    = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);

вы можете найти тему здесь:

Как я могу десериализовать JSON в простой словарь‹string,string› в ASP.NET?

надеюсь, что это поможет (хотя и не уверен на 100%, как это работает со сложными древовидными структурами)

person jim tollan    schedule 31.01.2011
comment
Дэвид, я знаю :-), отсюда и моя дополнительная информация об этой библиотеке. я на самом деле сослался на дополнительный ответ исключительно на основе этого, иначе я бы «сделал вершину еще» - не беспокойтесь (значок подмигивания) - person jim tollan; 31.01.2011

Это способ MS сделать это, но он довольно сложный, и я действительно думаю, что решение YvesR может быть проще в реализации.

http://atsung.wordpress.com/2008/08/07/javascriptserializer-example/

person David Mårtensson    schedule 31.01.2011
comment
YvesR -это был не я :-}. я тоже думаю, что это был плохой минус. я ненавижу, когда это происходит, и комментарий не остается!! - без разницы - person jim tollan; 31.01.2011

Чтобы преобразовать ассоциативный массив js в словарь, можно использовать конвертер, который выглядит следующим образом:

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace MyJsonConverters
{
    public class AssosiativeArrayConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType.GetInterface(typeof(IDictionary<,>).Name) != null;
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JObject jObject = JObject.Load(reader);

            var result = Activator.CreateInstance(objectType);
            var addMethod = result.GetType().GetMethod("Add");
            var dictionaryTypes = objectType.GetGenericArguments();

            foreach (JProperty property in jObject.Properties())
            {
                var key = Convert.ChangeType(property.Name, dictionaryTypes[0]);

                var value = serializer.Deserialize(property.Value.CreateReader(), dictionaryTypes[1]);

                addMethod.Invoke(result, new[] { key, value });
            }

            return result;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
}

тогда использование выглядит следующим образом:

Dictionary<string, string> dictionary;
dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(value, new AssosiativeArrayConverter);

где T - ваш словарь, например. Словарь или что вам нравится.

Json, десериализованный в моем случае, выглядит следующим образом:

{ "MyDictionary": { "key1": [ "value1", "value2", "value3" ], "key2": [ ] }

person tekado    schedule 22.11.2012
comment
эй, хороший подход +1 - person jim tollan; 17.05.2014

Я знаю, что это неправильный ответ прямо на ваш вопрос, но для всего, что связано с JSON на С#, вот ссылка на очень хорошую библиотеку, которую вы можете использовать, чтобы легко делать что-либо с JSON на С#.

http://james.newtonking.com/pages/json-net.aspx

person YvesR    schedule 31.01.2011
comment
На самом деле я использую библиотеку JSON.NET в своем вопросе. Это было частью проблемы. - person PandaWood; 26.07.2013