Reputation: 2687
I am trying to use the Northwind OData service:
http://services.odata.org/V3/OData/OData.svc/Products?$format=json
and deserialize it to a collection of products:
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(new Uri(url));
ObservableCollection<Product> products = await response.Content.ReadAsAsync<ObservableCollection<Product>>();
}
But the serializer doesn't seem to like the odata.metadata
part and the fact that there are 2 odata.type
records there (not sure what they are).
Is there an easy way to do this?
Upvotes: 33
Views: 45766
Reputation: 89
Another way to handle it is to use JObject Data
JsonConvert.DeserializeObject<JObject>(response)["value"].ToObject<List<Product>>()
Upvotes: 3
Reputation: 51
Another potential way to manage the deserialisation problem caused by the odata.metadata
part is to request that the odata response doesn't contain the metadata. This can be done with a default request header in the http client:
client.DefaultRequestHeaders.Add("Accept", "application/json;odata.metadata=none");
Which allows the object to then be deserialised with ReadAsAsync:
var products = response.Content.ReadAsAsync<Dictionary<string, ObservableCollection<Product>>>().Result["value"]
This seems much cleaner than having to write another class to handle the response. Using .Result
might not be the best way as the code isn't then asynchronous, but it wasn't important in my application and made the code occupy fewer lines.
Upvotes: 5
Reputation: 3234
Define a class for the response from odata (Its a generic definition so you can use this with any type):
internal class ODataResponse<T>
{
public List<T> Value { get; set; }
}
Deserialize like this:
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;
}
Upvotes: 36
Reputation: 1363
If you are using Visual Studio there is a fantastic CLR Class Generation feature built in.
You can then use Json.NET to deserialize into these classes (as described in L.B's answer).
Upvotes: 15
Reputation: 1098
There are .NET client for directly consuming OData services. For V3 odata service, you can try with Simple.OData.Client , ODataLib for OData v1-3. For V3 OData service, you can try with OData Client Code Generator. Other libraries for OData client, you can refer to http://www.odata.org/libraries/ .
Upvotes: 5
Reputation: 116118
Using 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; }
}
Upvotes: 46