在C#中解析JSON键值对

3

参考C#中解析JSON

我正在尝试在C#中解析以下JSON源,但我在访问“rates”中的数据时遇到了问题。我已经尝试将其反序列化为List>或Dictionary和其他各种类型,但始终获取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

我正在使用JSON.net(文档在此处),它可能类似于DataContractJsonSerializer,但我只是用Dictionary<string,decimal>替换了你的RatesObj

[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个字符串(货币名称)和小数(汇率)的rates属性。希望这正是您所需要的。
希望这可以帮到您。如果您有其他问题,请告诉我,我会详细解答。
祝好运!

0

个人认为如果可以使用IExtensibleDataObject来处理这些事情将会非常好,但由于ExtensionDataObject是完全不透明的,因此明确禁止使用。当然,您可以使用反射提取内部字典,但如果这样做,行为没有任何保证。

可以使用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

我同意JSON.net更优秀,但这并没有真正回答他的问题。他想要摆脱RateObj并使用更动态的东西。 - David Hoerster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接