Подтвердить что ты не робот

Преобразование свойств/токенов JSON.NET JObject в словарные ключи

Я использую JSON.NET для анализа ответа JSON на стороне сервера openexhangerates.org с помощью .NET. Ответ содержит вложенный объект ( "ставки" ), который имеет длинный список числовых свойств:

    {
    "disclaimer": "Exchange rates provided for informational purposes only, with no guarantee whatsoever of accuracy, validity, availability, or fitness for any purpose; use at your own risk. Other than that, have fun! Usage subject to acceptance of terms: http://openexchangerates.org/terms/",
    "license": "Data sourced from various providers with public-facing APIs; copyright may apply; not for resale; no warranties given. Usage subject to acceptance of license agreement: http://openexchangerates.org/license/",
        "timestamp": 1357268408,
        "base": "USD",
        "rates": {
            "AED": 3.673033,
            "AFN": 51.5663,
            "ALL": 106.813749,
            "AMD": 403.579996,
            etc...
        }
    }

Имена свойств соответствуют типу валюты (например, "USD" ). Мне нужно предположить, что список свойств может меняться со временем, поэтому я хочу преобразовать объект в словарь вместо соответствующего объекта С#.

Итак, вместо десериализации объекта JSON что-то вроде этого:

class Rates
{
public decimal AED; // United Arab Emirates Dirham
public decimal AFN; // Afghan Afghani
public decimal ALL; // Albanian Lek
public decimal AMD; // Armenian Dram
// etc...
}

Я хочу закончить с этим:

Dictionary<string,decimal>() {{"AED",0.2828},{"AFN",0.3373},{"ALL",2.2823},{"AMD",33.378} // etc...};

Как это сделать, начиная с строки ответа или из объекта JObject, созданного вызовом JObject.Parse(responseString)?

4b9b3361

Ответ 1

JObject уже реализует IDictionary<string, JToken>, поэтому я подозреваю, что, когда вы переходите к члену rates, вы должны иметь возможность использовать:

var result = rates.ToDictionary(pair => pair.Key, pair => (decimal) pair.Value);

К сожалению, он использует явную реализацию интерфейса, что немного больно, но если вы проходите через интерфейс IDictionary<string, JToken>, это нормально.

Вот короткий, но полный пример, который, как представляется, работает с JSON, который вы предоставили (сохранен в файле test.json):

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

class Test
{
    static void Main()
    {
        JObject parsed = JObject.Parse(File.ReadAllText("test.json"));
        IDictionary<string, JToken> rates = (JObject) parsed["rates"];
        // Explicit typing just for "proof" here
        Dictionary<string, decimal> dictionary =
            rates.ToDictionary(pair => pair.Key,
                               pair => (decimal) pair.Value);
        Console.WriteLine(dictionary["ALL"]);
    }
}

Ответ 2

Это работает для вас?

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

namespace JsonNetTest
{



    class Program
    {
        static void Main(string[] args)
        {

            string jsonString = @"{
                'disclaimer': 'Exchange rates provided for informational purposes only, with no guarantee whatsoever of accuracy, validity, availability, or fitness for any purpose; use at your own risk. Other than that, have fun! Usage subject to acceptance of terms: http://openexchangerates.org/terms/',
                'license': 'Data sourced from various providers with public-facing APIs; copyright may apply; not for resale; no warranties given. Usage subject to acceptance of license agreement: http://openexchangerates.org/license/',
                'timestamp': 1357268408,
                'base': 'USD',
                'rates': {
                    'AED': 3.673033,
                    'AFN': 51.5663,
                    'ALL': 106.813749,
                    'AMD': 403.579996
                }
            }";

            JObject parsed = JObject.Parse(jsonString);

            Dictionary<string, decimal> rates = parsed["rates"].ToObject<Dictionary<string, decimal>>();

            Console.WriteLine(rates["ALL"]);

            Console.ReadKey();

        }
    }
}

Ответ 3

Если вы ожидаете, что дочерний объект имеет свойство объекта (или поле), лучше использовать:

Dictionary<string, object> rates = parsed["rates"].ToObject<Dictionary<string, object>>();

В противном случае это вызовет ошибку.