Использование JSON.NET для доступа к атрибутам JSON для создания словаря C # - PullRequest
6 голосов
/ 31 января 2011

Я хочу преобразовать словарь в 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);
}

РЕДАКТИРОВАТЬ : Благодаря @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);

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

Ответы [ 4 ]

11 голосов
/ 31 января 2011

Panda,

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

// Json.NET does this...

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

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

Какможно десериализовать JSON в простой словарьв ASP.NET?

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

2 голосов
/ 31 января 2011

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

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

1 голос
/ 22 ноября 2012

Чтобы преобразовать ассоциативный массив 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": { "ключ1": [ "Value1", «Значение2», "Value3" ], "ключ2": [] }

0 голосов
/ 31 января 2011

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

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

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