Разбор пар ключ-значение JSON в C # - PullRequest
3 голосов
/ 25 января 2012

Со ссылкой на Анализ JSON в C #

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

Вот мои текущие DataContracts:

    [DataContract]
    public class OpenExchangeRatesResult
    {
        public OpenExchangeRatesResult() { }

        [DataMember]
        public string disclaimer { get; set; }

        [DataMember]
        public RatesObj rates { get; set; }

    }

    [DataContract]
    public class RatesObj
    {
        public RatesObj() { }
        [DataMember]
        public decimal EUR { get; set; }
        [DataMember]
        public decimal USD { get; set; }
        [DataMember]
        public decimal GBP { get; set; }
        [DataMember]
        public decimal AUD { get; set; }
        [DataMember]
        public decimal CAD { get; set; }
        [DataMember]
        public decimal CHF { get; set; }
        [DataMember]
        public decimal DKK { get; set; }
        [DataMember]
        public decimal LYD { get; set; }
        [DataMember]
        public decimal NZD { get; set; }
        [DataMember]
        public decimal SEK { get; set; }
        [DataMember]
        public decimal JPY { get; set; }
        [DataMember]
        public decimal ZAR { get; set; }
    }

Я хотел бы иметь возможность заменить RatesObj на какую-то коллекцию.

Есть идеи?

Ответы [ 3 ]

3 голосов
/ 25 января 2012

Я использую JSON.net (документация здесь ), что, вероятно, аналогично DataContractJsonSerializer, но я только заменил ваш RatesObj на Dictionary<string,decimal>:

[DataContract]
public class OpenExchangeRatesResult
{
    public OpenExchangeRatesResult() { }
    [DataMember]
    public string disclaimer { get; set; }
    [DataMember]
    public Dictionary<string, decimal> rates { get; set; }
}

И мой тестовый код:

class Program
{
    static void Main(string[] args)
    {
        HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(@"https://raw.github.com/currencybot/open-exchange-rates/master/latest.json");
        wr.Timeout = 30 * 1000;
        HttpWebResponse response = (HttpWebResponse)wr.GetResponse();
        using (var s = new StreamReader(response.GetResponseStream()))
        {
            string json = s.ReadToEnd();

            var oerr = JsonConvert.DeserializeObject<OpenExchangeRatesResult>(json);

            Console.WriteLine(json);
        }
    }
}

Я получаю в итоге свойство со ставками, содержащее около 150 записей строк (название валюты) и десятичных дробей (курсы). Надеюсь, это то, что вы ищете.

Надеюсь, это поможет. Дайте мне знать, если у вас есть другие вопросы, и я разработаю свой ответ.

Удачи!

0 голосов
/ 25 января 2012

(ИМХО было бы замечательно, если бы IExtensibleDataObject мог использоваться для такого рода вещей, но так как ExtensionDataObject полностью непрозрачен, он явно запрещен. Конечно, вы можете извлечь внутренний словарь, используя Reflection, но нет никаких гарантий для поведения, если вы это сделаете так)

Можно использовать: JsonReaderWriterFactory.CreateJsonReader для создания объекта XmlReader, который позволяет использовать более динамическую схему. Использование XmlReaders в большинстве случаев болезненно, поэтому я не могу утверждать, что этот код идеален, но, возможно, он может послужить источником вдохновения.

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Xml;

namespace ConsoleApplication1
{

    class Program
    {
        static dynamic RecursiveBuildUp (XmlReader reader)
        {
            object result = null;
            while (reader.Read ())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        // TODO: It seems array elements are identified with the an "item" key
                        // This can create problems if the json object has a property name "item"
                        if (reader.LocalName == "item")
                        {
                            var list = result as List<object>;
                            if (list == null)
                            {
                                list = new List<object>();
                                result = list;
                            }
                            list.Add (RecursiveBuildUp (reader));
                        }
                        else
                        {
                            var dic = result as IDictionary<string, object>;
                            if (dic == null)
                            {
                                dic = new ExpandoObject ();
                                result = dic;
                            }
                            var localName = reader.LocalName;
                            dic[localName] = RecursiveBuildUp (reader);
                        }
                        break;
                    case XmlNodeType.Text:
                        result = reader.Value;
                        break;
                    case XmlNodeType.EndElement:
                        return result;
                    default:
                        throw new Exception ("Unhandled node type: " + reader.NodeType);
                }
            }
            return result;
        }

        static void Main (string[] args)
        {
            var wc = new WebClient ();
            var json = wc.DownloadData ("https://raw.github.com/currencybot/open-exchange-rates/master/latest.json");

            var quotas = new XmlDictionaryReaderQuotas ();
            var reader = JsonReaderWriterFactory.CreateJsonReader (json, quotas);

            var result = RecursiveBuildUp (reader);
            Console.WriteLine (result.root.rates.AED);
        }
    }
}
0 голосов
/ 25 января 2012

Попробуйте JSon.Net, это отличная библиотека.

http://json.codeplex.com

...