c# - filters - ¿Cómo deserializar oData JSON?
odata v4 (5)
Estoy tratando de usar el servicio OData de Northwind:
http://services.odata.org/V3/OData/OData.svc/Products?$format=json
Y deserializarlo en una colección de productos:
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(new Uri(url));
ObservableCollection<Product> products = await response.Content.ReadAsAsync<ObservableCollection<Product>>();
}
Pero al serializador no parece gustarle la parte odata.metadata
y el hecho de que hay 2 registros odata.type
allí (no estoy seguro de lo que son).
¿Hay una forma fácil de hacer esto?
Defina una clase para la respuesta de odata (es una definición genérica para que pueda usar esto con cualquier tipo):
internal class ODataResponse<T>
{
public List<T> Value { get; set; }
}
Deserializar así:
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(new Uri(url));
var json = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<ODataResponse<Product>>(json);
var products = result.Value;
}
Hay cliente .NET para consumir directamente los servicios OData. Para el servicio odata V3, puedes probar con Simple.OData.Client , ODataLib para OData v1-3 . Para el servicio V3 OData, puedes probar con OData Client Code Generator . Otras bibliotecas para el cliente OData, puede consultar http://www.odata.org/libraries/ .
Otra forma potencial de administrar el problema de deserialización causado por la parte odata.metadata
es solicitar que la respuesta de odata no contenga los metadatos. Esto se puede hacer con un encabezado de solicitud predeterminado en el cliente http:
client.DefaultRequestHeaders.Add("Accept", "application/json;odata.metadata=none");
Lo que permite que el objeto se deserialice con ReadAsAsync:
var products = response.Content.ReadAsAsync<Dictionary<string, ObservableCollection<Product>>>().Result["value"]
Esto parece mucho más limpio que tener que escribir otra clase para manejar la respuesta. El uso de .Result
puede no ser la mejor manera, ya que el código no es asíncrono, pero no fue importante en mi aplicación e hizo que el código ocupara menos líneas.
Si está utilizando Visual Studio, hay una fantástica función CLR Class Generation incorporada.
- Copia una carga de OData en tu portapapeles
- En Visual Studio, seleccione la opción de menú Editar -> Pegado especial -> Pegar JSON como clases de objetos
Luego puede usar Json.NET para deserializar en estas clases (como se describe en la respuesta de LB).
Usando Json.Net
using (var client = new HttpClient())
{
var json = await client.GetStringAsync("http://services.odata.org/V3/OData/OData.svc/Products?$format=json");
var odata = JsonConvert.DeserializeObject<OData>(json);
}
public class Value
{
[JsonProperty("odata.type")]
public string Type { set; get; }
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime ReleaseDate { get; set; }
public DateTime? DiscontinuedDate { get; set; }
public int Rating { get; set; }
public double Price { get; set; }
}
public class OData
{
[JsonProperty("odata.metadata")]
public string Metadata { get; set; }
public List<Value> Value { get; set; }
}