web-dev-qa-db-fra.com

Comment désérialiser oData JSON?

J'essaie d'utiliser le service Northwind OData:

http://services.odata.org/V3/OData/OData.svc/Products?$format=json

et le désérialiser dans une collection de produits:

    using (var client = new HttpClient())
    {
        HttpResponseMessage response = await client.GetAsync(new Uri(url));
        ObservableCollection<Product> products = await response.Content.ReadAsAsync<ObservableCollection<Product>>();
    }

Mais le sérialiseur ne semble pas aimer la partie odata.metadata et le fait qu’il existe 2 enregistrements odata.type (pas sûr de ce qu’ils sont).

Y a-t-il un moyen facile de faire ceci? 

17
Graeme

Utiliser 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; }
}
32
L.B

Définissez une classe pour la réponse de odata (c'est une définition générique pour pouvoir l'utiliser avec n'importe quel type):

internal class ODataResponse<T>
 {
    public List<T> Value { get; set; }
 }

Désérialiser comme ceci:

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;
 }
12
ozanmut

Si vous utilisez Visual Studio, une fonctionnalité fantastique de génération de classes CLR est intégrée.

  1. Copier une charge OData dans votre presse-papiers
  2. Dans Visual Studio, sélectionnez l’option de menu Edition -> Collage spécial -> Coller JSON en tant que classes d’objet.

Vous pouvez ensuite utiliser Json.NET pour désérialiser ces classes (comme décrit dans la réponse de L.B).

7
ScottB

Il existe un client .NET pour consommer directement des services OData. Pour le service V3 odata, vous pouvez essayer avec Simple.OData.Client , ODataLib pour OData v1-3 . Pour le service V3 OData, vous pouvez essayer avec OData Client Code Generator . Pour les autres bibliothèques du client OData, vous pouvez vous référer à http://www.odata.org/libraries/ .

3
QianLi

Un autre moyen possible de gérer le problème de désérialisation provoqué par la partie odata.metadata consiste à demander que la réponse odata ne contienne pas les métadonnées. Cela peut être fait avec un en-tête de requête par défaut dans le client http:

client.DefaultRequestHeaders.Add("Accept", "application/json;odata.metadata=none");

Ce qui permet ensuite de désérialiser l'objet avec ReadAsAsync:

var products = response.Content.ReadAsAsync<Dictionary<string, ObservableCollection<Product>>>().Result["value"]

Cela semble beaucoup plus simple que de devoir écrire une autre classe pour gérer la réponse. Utiliser .Result n'est peut-être pas la meilleure solution car le code n'est pas asynchrone à ce moment-là, mais ce n'était pas important dans mon application et le code occupait moins de lignes.

0
Rand0mChar