关于c#:将JSON.NET JObject的属性/标记转换为字典键

Converting a JSON.NET JObject's Properties/Tokens into Dictionary Keys

我正在使用JSON.NET使用.NET解析来自openexhangerates.org服务器端的JSON响应。 响应包含一个嵌套对象("rates"),它有一长串数字属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
    {
   "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")。 我需要假设属性列表可以随时间变化,所以我想将对象转换为Dictionary而不是相应的C#对象。

所以不是将JSON对象反序列化为这样的东西:

1
2
3
4
5
6
7
8
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...
}

我想最终得到这个:

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

如何从响应字符串或通过调用JObject.Parse(responseString)生成的JObject开始?


JObject已经实现IDictionary,所以我怀疑当你导航到rates成员时,你应该可以使用:

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

不幸的是,它使用显式接口实现,这使得这有点痛苦 - 但如果你通过IDictionary接口,它没关系。

这是一个简短但完整的示例,它似乎与您提供的JSON一起使用(保存到test.json文件中):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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"]);
    }
}


这对你有用吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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();

        }
    }
}


如果您希望子对象具有对象属性(或字段),则最好使用:

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

否则,它将抛出一个错误。