I am attempting to deserialise results from the OctoPart API (http://octopart.com/api/docs/v3/rest-api) using c# and json.net
There are no issues deserialising the majority of the data, however I am running troubles with the Part.specs attributes (http://octopart.com/api/docs/v3/rest-api#notes-part.specs) because the attributes change depending on the item returned.
Here is what the API says about Part.Specs
The specs attribute attached to Part instances is a JSON object mapping attribute short names (e.g. "voltage_rating_dc") to QualitativeValue and QuantitativeValue instances.
It's important to note that all value properties of (Qual|Quant)itativeValue objects are JSON arrays. The reason for this is to accomodate multi-valued attributes such as power supplies with multiple output voltages:
Because I want to maintain the class, I believe that I might need to implement a custom JConverter?
I was looking at this question, but wasnt too sure how to apply to this example beccause the attributes can be deserialised into the QualitativeValue / QuantitativeValue classes
Here is my Part class
public class Part
{
public string __class__ { get; set; }
public string uid { get; set; }
public long uid_v2 { get; set; }
public string mpn { get; set; }
public Manufacturer manufacturer { get; set; }
public Brand brand { get; set; }
public string octopart_url { get; set; }
public List<PartOffer> offers { get; set; }
public List<Datasheet> datasheets { get; set; }
public List<ComplianceDocument> compliance_documents { get; set; }
public List<Description> descriptions { get; set; }
public List<ImageSet> imagesets { get; set; }
public Dictionary<string, string> specs { get; set; }
public List<string> category_uids { get; set; }
public List<ExternalLinks> external_links { get; set; }
}
Here is an example result (PartsMatchResponse) from the API
{
"__class__": "PartsMatchResponse",
"msec": 183,
"request": {
"__class__": "PartsMatchRequest",
"exact_only": false,
"queries": [
{
"__class__": "PartsMatchQuery",
"brand": null,
"limit": 10,
"mpn": "ERJ8BWFR010V",
"mpn_or_sku": null,
"q": "",
"reference": null,
"seller": null,
"sku": null,
"start": 0
}
]
},
"results": [
{
"__class__": "PartsMatchResult",
"error": null,
"hits": 1,
"items": [
{
"__class__": "Part",
"brand": {
"__class__": "Brand",
"name": "Panasonic - ECG",
"uid": "4c528d5878c09b95"
},
"category_uids": [
"7542b8484461ae85",
"cd01000bfc2916c6",
"5c6a91606d4187ad"
],
"compliance_documents": [],
"datasheets": null,
"external_links": {
"__class__": "ExternalLinks",
"evalkit_url": null,
"freesample_url": null,
"product_url": null
},
"imagesets": null,
"manufacturer": {
"__class__": "Manufacturer",
"name": "Panasonic - ECG",
"uid": "c20a0700af7c11cd"
},
"mpn": "ERJ8BWFR010V",
"octopart_url": "http://octopart.com/erj8bwfr010v-panasonic+-+ecg-7979066",
"offers": null,
"specs": {
"case_package": {
"__class__": "QualitativeValue",
"attribution": {
"__class__": "Attribution",
"first_acquired": null,
"sources": []
},
"value": [
"1206"
]
},
"case_package_si": {
"__class__": "QualitativeValue",
"attribution": {
"__class__": "Attribution",
"first_acquired": null,
"sources": []
},
"value": [
"3216"
]
},
"lead_free_status": {
"__class__": "QualitativeValue",
"attribution": {
"__class__": "Attribution",
"first_acquired": null,
"sources": [
{
"__class__": "Source",
"name": "Future Electronics",
"uid": "e4032109c4f337c4"
}
]
},
"value": [
"Lead Free"
]
},
"lifecycle_status": {
"__class__": "QualitativeValue",
"attribution": {
"__class__": "Attribution",
"first_acquired": null,
"sources": []
},
"value": [
"Not Listed by Manufacturer"
]
},
"pin_count": {
"__class__": "QuantitativeValue",
"attribution": {
"__class__": "Attribution",
"first_acquired": null,
"sources": [
{
"__class__": "Source",
"name": "Farnell",
"uid": "58989d9272cd8b5f"
}
]
},
"max_value": null,
"min_value": null,
"unit": null,
"value": [
"2"
]
},
"power_rating": {
"__class__": "QuantitativeValue",
"attribution": {
"__class__": "Attribution",
"first_acquired": null,
"sources": [
{
"__class__": "Source",
"name": "Newark",
"uid": "d294179ef2900153"
}
]
},
"max_value": null,
"min_value": null,
"unit": null,
"value": [
"0.5"
]
},
"resistance": {
"__class__": "QuantitativeValue",
"attribution": {
"__class__": "Attribution",
"first_acquired": null,
"sources": [
{
"__class__": "Source",
"name": "Farnell",
"uid": "58989d9272cd8b5f"
}
]
},
"max_value": null,
"min_value": null,
"unit": null,
"value": [
"0.01"
]
},
"resistance_tolerance": {
"__class__": "QualitativeValue",
"attribution": {
"__class__": "Attribution",
"first_acquired": null,
"sources": []
},
"value": [
"\u00b11%"
]
},
"rohs_status": {
"__class__": "QualitativeValue",
"attribution": {
"__class__": "Attribution",
"first_acquired": null,
"sources": [
{
"__class__": "Source",
"name": "Newark",
"uid": "d294179ef2900153"
}
]
},
"value": [
"Compliant"
]
}
},
"uid": "69e8a09b8cb4b62f",
"uid_v2": 797906654705
}
],
"reference": null
}
]
}
Yes, you will need a custom JsonConverter to solve this. Basically what you need to do is this:
Define your QualitativeValue and QuantitativeValue classes to have a common base class (e.g. AbstractQValue) or interface.
In your Parts class, make the specs property a Dictionary<string, AbstractQValue>. This will handle the changing attribute names.
Create a custom JsonConverter to handle the instantiation of the concrete QualitativeValue or QuantitativeValue based on the __class__ attribute in the JSON. See this answer for an example of how to implement this.
Lastly, when you do your deserialization, be sure to pass an instance of the custom JsonConverter into the JsonConvert.DeserializeObject method.
Demo
I had a little time, so I threw together a working example. Here are the class definitions for the data (I cut out most of the extraneous stuff for brevity):
public class PartsMatchResponse
{
public List<PartsMatchResult> results { get; set; }
}
public class PartsMatchResult
{
public List<Part> items { get; set; }
}
public class Part
{
public Manufacturer manufacturer { get; set; }
public string mpn { get; set; }
public Dictionary<string, AbstractQValue> specs { get; set; }
}
public class Manufacturer
{
public string name { get; set; }
}
public abstract class AbstractQValue
{
public List<string> value { get; set; }
}
public class QualitativeValue : AbstractQValue
{
}
public class QuantitativeValue : AbstractQValue
{
public string unit { get; set; }
}
Here is the custom JsonConverter class:
public class QValueJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(AbstractQValue).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader,
Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
if (jo["__class__"].ToString() == "QuantitativeValue")
{
return jo.ToObject<QuantitativeValue>();
}
return jo.ToObject<QualitativeValue>();
}
public override void WriteJson(JsonWriter writer,
object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Here is a demo program showing how to use the converter when deserializing:
class Program
{
static void Main(string[] args)
{
// (jsonString is defined as a constant below)
PartsMatchResponse response =
JsonConvert.DeserializeObject<PartsMatchResponse>(jsonString,
new QValueJsonConverter());
foreach (Part part in response.results[0].items)
{
Console.WriteLine("manufacturer: " + part.manufacturer.name);
Console.WriteLine("mfr. part no: " + part.mpn);
foreach (KeyValuePair<string, AbstractQValue> kvp in part.specs)
{
string unit = "";
if (kvp.Value is QuantitativeValue)
unit = ((QuantitativeValue)kvp.Value).unit;
Console.WriteLine(kvp.Key + ": " +
string.Join(", ", kvp.Value.value) + " " + unit);
}
Console.WriteLine();
}
}
// Note: this is the same as the example JSON in the question, except
// I added units for some of the QuantitativeValue specs for demo purposes.
const string jsonString = #"
{
""__class__"": ""PartsMatchResponse"",
""msec"": 183,
""request"": {
""__class__"": ""PartsMatchRequest"",
""exact_only"": false,
""queries"": [
{
""__class__"": ""PartsMatchQuery"",
""brand"": null,
""limit"": 10,
""mpn"": ""ERJ8BWFR010V"",
""mpn_or_sku"": null,
""q"": """",
""reference"": null,
""seller"": null,
""sku"": null,
""start"": 0
}
]
},
""results"": [
{
""__class__"": ""PartsMatchResult"",
""error"": null,
""hits"": 1,
""items"": [
{
""__class__"": ""Part"",
""brand"": {
""__class__"": ""Brand"",
""name"": ""Panasonic - ECG"",
""uid"": ""4c528d5878c09b95""
},
""category_uids"": [
""7542b8484461ae85"",
""cd01000bfc2916c6"",
""5c6a91606d4187ad""
],
""compliance_documents"": [],
""datasheets"": null,
""external_links"": {
""__class__"": ""ExternalLinks"",
""evalkit_url"": null,
""freesample_url"": null,
""product_url"": null
},
""imagesets"": null,
""manufacturer"": {
""__class__"": ""Manufacturer"",
""name"": ""Panasonic - ECG"",
""uid"": ""c20a0700af7c11cd""
},
""mpn"": ""ERJ8BWFR010V"",
""octopart_url"": ""http://octopart.com/erj8bwfr010v-panasonic+-+ecg-7979066"",
""offers"": null,
""specs"": {
""case_package"": {
""__class__"": ""QualitativeValue"",
""attribution"": {
""__class__"": ""Attribution"",
""first_acquired"": null,
""sources"": []
},
""value"": [
""1206""
]
},
""case_package_si"": {
""__class__"": ""QualitativeValue"",
""attribution"": {
""__class__"": ""Attribution"",
""first_acquired"": null,
""sources"": []
},
""value"": [
""3216""
]
},
""lead_free_status"": {
""__class__"": ""QualitativeValue"",
""attribution"": {
""__class__"": ""Attribution"",
""first_acquired"": null,
""sources"": [
{
""__class__"": ""Source"",
""name"": ""Future Electronics"",
""uid"": ""e4032109c4f337c4""
}
]
},
""value"": [
""Lead Free""
]
},
""lifecycle_status"": {
""__class__"": ""QualitativeValue"",
""attribution"": {
""__class__"": ""Attribution"",
""first_acquired"": null,
""sources"": []
},
""value"": [
""Not Listed by Manufacturer""
]
},
""pin_count"": {
""__class__"": ""QuantitativeValue"",
""attribution"": {
""__class__"": ""Attribution"",
""first_acquired"": null,
""sources"": [
{
""__class__"": ""Source"",
""name"": ""Farnell"",
""uid"": ""58989d9272cd8b5f""
}
]
},
""max_value"": null,
""min_value"": null,
""unit"": null,
""value"": [
""2""
]
},
""power_rating"": {
""__class__"": ""QuantitativeValue"",
""attribution"": {
""__class__"": ""Attribution"",
""first_acquired"": null,
""sources"": [
{
""__class__"": ""Source"",
""name"": ""Newark"",
""uid"": ""d294179ef2900153""
}
]
},
""max_value"": null,
""min_value"": null,
""unit"": ""Watt"",
""value"": [
""0.5""
]
},
""resistance"": {
""__class__"": ""QuantitativeValue"",
""attribution"": {
""__class__"": ""Attribution"",
""first_acquired"": null,
""sources"": [
{
""__class__"": ""Source"",
""name"": ""Farnell"",
""uid"": ""58989d9272cd8b5f""
}
]
},
""max_value"": null,
""min_value"": null,
""unit"": ""Ohm"",
""value"": [
""0.01""
]
},
""resistance_tolerance"": {
""__class__"": ""QualitativeValue"",
""attribution"": {
""__class__"": ""Attribution"",
""first_acquired"": null,
""sources"": []
},
""value"": [
""\u00b11%""
]
},
""rohs_status"": {
""__class__"": ""QualitativeValue"",
""attribution"": {
""__class__"": ""Attribution"",
""first_acquired"": null,
""sources"": [
{
""__class__"": ""Source"",
""name"": ""Newark"",
""uid"": ""d294179ef2900153""
}
]
},
""value"": [
""Compliant""
]
}
},
""uid"": ""69e8a09b8cb4b62f"",
""uid_v2"": 797906654705
}
],
""reference"": null
}
]
}";
}
And finally, here is the output of the above program:
manufacturer: Panasonic - ECG
mfr. part no: ERJ8BWFR010V
case_package: 1206
case_package_si: 3216
lead_free_status: Lead Free
lifecycle_status: Not Listed by Manufacturer
pin_count: 2
power_rating: 0.5 Watt
resistance: 0.01 Ohm
resistance_tolerance: ±1%
rohs_status: Compliant
You'll need these classes to model the JSON
public class OctopartObject
{
public string __class__ { get; set; }
public int msec { get; set; }
public Request request { get; set; }
public List<Result> results { get; set; }
}
public class Query
{
public string __class__ { get; set; }
public object brand { get; set; }
public int limit { get; set; }
public string mpn { get; set; }
public object mpn_or_sku { get; set; }
public string q { get; set; }
public object reference { get; set; }
public object seller { get; set; }
public object sku { get; set; }
public int start { get; set; }
}
public class Request
{
public string __class__ { get; set; }
public bool exact_only { get; set; }
public List<Query> queries { get; set; }
}
public class Brand
{
public string __class__ { get; set; }
public string name { get; set; }
public string uid { get; set; }
}
public class Manufacturer
{
public string __class__ { get; set; }
public string name { get; set; }
public string uid { get; set; }
}
public class Item
{
public string __class__ { get; set; }
public Brand brand { get; set; }
public Manufacturer manufacturer { get; set; }
public string mpn { get; set; }
public string octopart_url { get; set; }
public List<object> offers { get; set; }
public string uid { get; set; }
public object uid_v2 { get; set; }
}
public class Result
{
public string __class__ { get; set; }
public object error { get; set; }
public int hits { get; set; }
public List<Item> items { get; set; }
public object reference { get; set; }
}
Then using JSON.NET & .NET 4.5, do something like this.
HttpClient client = new HttpClient();
// Send a request asynchronously and continue when complete
HttpResponseMessage clientResult = await client.GetAsync(_address);
// Check that response was successful or throw exception
clientResult.EnsureSuccessStatusCode();
// Read response asynchronously as JToken and write out top facts for each country
string jsonString = await clientResult.Content.ReadAsStringAsync();
OctopartObject obj = JsonConvert.DeserializeObject<OctopartObject>(jsonString);
You'll have a nice object that should model the data received from the _address URI
I still haven't fully tested this, so there could be some issues. But I've been struggling for a few hours on this and finally found something that seems to be working. I'm sure it won't work for datasheets and any extra fields, as this only returns the basic. But I essentially just used this site to get the object models and changed the name of the root one to OctopartObject
Related
public class Job
{
public long Id { get; set; }
public long? JobId { get; set; }
public Job ParentJob { get; set; }
public ICollection<Job> ChildJobs { get; set; }
public string Name { get; set; }
}
var child = new Job { Name = "ChildJob" };
var parent = new Job { Name = "ParentJob", ChildJobs = new List<Job>()};
parent.ChildJobs.Add(child);
_context.Jobs.Add(parent);
_context.SaveChanges();
I added jobs like this: but why I get childJob duplicated?
[ { "id": 1, "jobId": null, "parentJob": null, "childJobs": [ { "id": 2, "jobId": 1, "childJobs": null, "name": "ChildJob" } ], "name": "ParentJob" }, { "id": 2, "jobId": 1, "parentJob": { "id": 1, "jobId": null, "parentJob": null, "childJobs": [], "name": "ParentJob" }, "childJobs": null, "name": "ChildJob" } ]
I tried to send a Dictionary.
This is the structure of my Dictionary:
var gridsAndCountriesByShipper = new Dictionary<Organisation, List<Grid>>();
And this is the class which the namespace appears instead of the object value:
namespace ez.webservice.PublicRestApi.DTO.References
{
[DataContract(Name = "organisation", Namespace = "")]
public class Organisation
{
[DataMember(Name = "id")]
public int Id { get; set; }
[DataMember(Name = "longName")]
public string LongName { get; set; }
[DataMember(Name = "shortName")]
public string ShortName { get; set; }
}
}
Finally this is the result when I send this object:
return Ok(gridsAndCountriesByShipper);
{
"ez.webservice.PublicRestApi.DTO.References.Organisation": [
{
"owner": {
"$id": "1",
"id": 2,
"longName": null,
"shortName": "Test"
},
"calendar": {
"id": 3,
"name": null,
"dotNetName": null,
"mySqlName": null,
"offset": 0
},
"country": {
"id": 13,
"name": "France",
"alpha2": "FR",
"alpha3": "FRA",
"grids": [],
"logo": {
"id": 13,
"name": "France",
"shortName": "FR"
}
},
"countryFlag": null,
"flag": "",
"granularity": "DAY",
I didn't find a solution.
Your Organisation doesn't override ToString() method and the default behavior is to return the class name with namespace
im facing a problem with probably selfreference Looping:
Model:
public class ProtectedAccount
{
public int Id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime Created { get; private set; }
public DateTime? Changed { get; set; }
public bool Disabled { get; set; }
public virtual ICollection<ProtectedAccountMember> Members { get; set; }
public virtual ProtectedAccountType Type { get; set; }
}
public class ProtectedAccountMember
{
public int Id { get; set; }
[StringLength(300)]
public string Name { get; set; }
[Index]
public virtual ProtectedAccount ProtectedAccount { get; set; }
}
Controller:
[ResponseType(typeof(ProtectedAccount))]
[Route("ProtectedAccounts/{id}/Members")]
[HttpGet]
public IHttpActionResult GetProtectedAccountMembers(int id)
{
var protectedAccount = db.ProtectedAccounts.Find(id);
if (protectedAccount == null)
{
return NotFound();
}
return Ok(protectedAccount.Members.ToList());
}
the data wich i receive for an GET seems to Loop recursive through all navigations:
[
{
"ProtectedAccount": {
"Members": [
{
"Id": 2,
"Name": "XXX, XX",
},
{
"Id": 3,
"Name": "XX, XX",
}
],
"Type": null,
"Id": 25,
"ObjectGUID": "76bf65e7-af60-4fe8-b3e1-90afbfd65b65",
"Name": "XXX",
},
"Id": 1,
"Name": "test",
},
{
"ProtectedAccount": {
"Members": [
{
"Id": 1,
"Name": "test",
},
{
"Id": 3,
"Name": "XX, XX",
"SamAccountName": "XX",
"Disabled": false
}
],
"Type": null,
"Id": 25,
"ObjectGUID": "76bf65e7-af60-4fe8-b3e1-90afbfd65b65",
"Name": "XXXX",
},
"Id": 2,
"Name": "XX, XX",
},
{
"ProtectedAccount": {a
"Members": [
{
"Id": 1,
"Name": "test",
"SamAccountName": "XXX",
"Disabled": false
},
{
"Id": 2,
"Name": "XX, XX",
"SamAccountName": "XX",
"Disabled": false
}
],
"Type": null,
"Id": 25,
"ObjectGUID": "76bf65e7-af60-4fe8-b3e1-90afbfd65b65",
"Name": "XXX",
},
"Id": 3,
"Name": "XX, XX",
}
]
There is only one "ProtectedAccount" in the database. DO i have to use DTO to overcome this issue? I tried some configuration via the json formatsettings but didnt get any better results.
From your code, you are only returing the protectedAccount.Members, hence you could do a projection query as below
var results = ctx.ProtectedAccountMembers
.Where(member => member.ProtectedAccount.Id == protectedAccount.Id)
.Select(member => new { member.Id, member.Name }).ToList();
I'm currently trying to read Json file (named initial_data.json) which reside in the folder DataModels in my Project folder. The problem I'm having is it won't read the file. I have tried the following code to read the file to json string (which I will use it to deserialize later, so I've tried to display it into resultTextBlock) and nothing has came out.
Here's my Json file format
{
"brands": [
{
"id": "AUD",
"name": "AUDI",
"sort": "99",
"active": true
},
{
"id": "BEN",
"name": "MERCEDES-BENZ",
"sort": "6",
"active": true
},
{
"id": "BMW",
"name": "BMW",
"sort": "7",
"active": true
},
{
"id": "CHE",
"name": "CHEVROLET",
"sort": "8",
"active": true
}
],
"models": [
{
"id": "100",
"name": "CIVIC",
"brandID": "HON",
"size": null,
"year": "-",
"active": true
},
{
"id": "101",
"name": "CRV",
"brandID": "HON",
"size": null,
"year": "-",
"active": true
},
{
"id": "102",
"name": "CRVEXI",
"brandID": "HON",
"size": null,
"year": "-",
"active": true
},
{
"id": "103",
"name": "GDYSSEY",
"brandID": "HON",
"size": null,
"year": "-",
"active": true
}
]
}
Here's my json Class
public class Brand
{
[JsonProperty("id")]
public string id { get; set; }
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("sort")]
public string sort { get; set; }
[JsonProperty("active")]
public bool active { get; set; }
[JsonProperty("path")]
public string path { get; set; }
}
public class Model
{
[JsonProperty("id")]
public string id { get; set; }
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("brandID")]
public string brandID { get; set; }
[JsonProperty("size")]
public object size { get; set; }
[JsonProperty("year")]
public string year { get; set; }
[JsonProperty("active")]
public bool active { get; set; }
}
And here's how I write my reading function
private async Task readJsonAsync()
{
// Notice that the write **IS** identical ... except for the serializer.
string content = String.Empty;
var myStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(JSONFILENAME);
using (StreamReader reader = new StreamReader(myStream))
{
content = await reader.ReadToEndAsync();
}
resultTextBlock.Text = content;
}
Any help would be appreciated
think there might be some issue with the path you specified for the file name.
Please put your file in assets folder and follow the below code
var fileStream = File.OpenRead("Assets/" + "sampleJson.txt");//You can specify your file name here.
using (StreamReader reader = new StreamReader(fileStream))
{
var content = await reader.ReadToEndAsync();
}
I'm trying to deserialize a json string and I'm getting the error End element 'caption' from namespace '' expected. Found element 'created_time' from namespace ''. when calling
InstagramObject test = (InstagramObject) instagramObject.ReadObject(instagramWebResponse.GetResponseStream());
The json from Instagram returns many elements but there are only a few that I need. My DataContract will be posted below.
Basically I need {data:[{caption: string, link: string, images: {...}}]}
Here's an example of the json...
{
"data": [{
"comments": {
"data": [],
"count": 0
},
"caption": {
"created_time": "1296710352",
"text": "Inside le truc #foodtruck",
"from": {
"username": "kevin",
"full_name": "Kevin Systrom",
"type": "user",
"id": "3"
},
"id": "26621408"
},
"likes": {
"count": 15,
"data": [{
"username": "mikeyk",
"full_name": "Mike Krieger",
"id": "4",
"profile_picture": "..."
}, {...subset of likers...}]
},
"link": "http://instagr.am/p/BWrVZ/",
"user": {
"username": "kevin",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_3_75sq_1295574122.jpg",
"id": "3"
},
"created_time": "1296710327",
"images": {
"low_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_6.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_5.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_7.jpg",
"width": 612,
"height": 612
}
},
"type": "image",
"filter": "Earlybird",
"tags": ["foodtruck"],
"id": "22721881",
"location": {
"latitude": 37.778720183610183,
"longitude": -122.3962783813477,
"id": "520640",
"street_address": "",
"name": "Le Truc"
}
}]
}
and here's my DataContract...
[DataContract]
public class InstagramObject {
[DataMember(Name = "data")]
public IEnumerable<InstagramData> instagramData { get; set; }
}
[DataContract]
public class InstagramData {
[DataMember(Name = "images")]
public List<InstagramImage> instagramImages { get; set; }
[DataMember(Name = "caption")]
public string caption { get; set; }
[DataMember(Name = "link")]
public string link { get; set; }
}
[DataContract]
public class InstagramImage {
[DataMember(Name = "low_resolution")]
public InstagramImageInfo lowResolutionImage { get; set; }
[DataMember(Name = "thumbnail")]
public InstagramImageInfo thumbnail { get; set; }
[DataMember(Name = "standard_resolution")]
public InstagramImageInfo standardResolution { get; set; }
}
[DataContract]
public class InstagramImageInfo {
[DataMember(Name = "url")]
public string url { get; set; }
[DataMember(Name = "width")]
public int width { get; set; }
[DataMember(Name = "height")]
public int height { get; set; }
}
In the data contract caption is declared as a string, but in the JSON caption is a record with various fields - caption should be declared to be an object with a compatible structure:
[DataContract]
public class InstagramCaption {
[DataMember(Name = "text")]
public string Text {get; set;}
}
. . .
[DataMember(Name = "caption")]
public InstagramCaption caption { get; set; }
. . .
No need to declare those clases If you want to go with Json.Net + Linq
var obj = (JObject)JsonConvert.DeserializeObject(json);
var result = obj["data"]
.Select(x => new {
Caption = (string)x["caption"]["text"],
Link = (string)x["link"],
Images = x["images"].Children()
.Select(y=>(string)y.First()["url"]).ToArray()
})
.ToArray();