Convertir las propiedades / tokens de JSON.NET JObject en claves de diccionario

Estoy usando JSON.NET para analizar una respuesta JSON desde el lado del servidor de openexhangerates.org usando .NET. La respuesta contiene un objeto nested (“tasas”) que tiene una larga lista de propiedades numéricas:

{ "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... } } 

Los nombres de las propiedades corresponden al tipo de moneda (por ejemplo, “USD”). Debo asumir que la lista de propiedades puede cambiar con el tiempo, por lo que quiero convertir el objeto en un Diccionario en lugar de un objeto C # correspondiente.

Así que en lugar de deserializar el objeto JSON en algo como esto:

 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... } 

Quiero terminar con esto:

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

¿Cómo hago esto comenzando desde la cadena de respuesta o desde el objeto JObject producido al llamar a JObject.Parse (responseString)?

JObject ya implementa IDictionary , por lo que sospecho que cuando haya navegado hasta el miembro de rates , debería poder usar:

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

Desafortunadamente, utiliza una implementación de interfaz explícita, lo que hace que esto sea un poco IDictionary , pero si pasa a través de la IDictionary , está bien.

Este es un ejemplo breve pero completo que parece funcionar con el JSON que ha proporcionado (guardado en un archivo 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 rates = (JObject) parsed["rates"]; // Explicit typing just for "proof" here Dictionary dictionary = rates.ToDictionary(pair => pair.Key, pair => (decimal) pair.Value); Console.WriteLine(dictionary["ALL"]); } } 

¿Esto funciona para tí?

 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 rates = parsed["rates"].ToObject>(); Console.WriteLine(rates["ALL"]); Console.ReadKey(); } } } 

Si está esperando que el objeto hijo tenga una propiedad (o campo) de objeto, es mejor usar:

 Dictionary rates = parsed["rates"].ToObject>(); 

De lo contrario, arrojará un error.