Parse json file without key values - c#
I'm trying to parse a json file with Json.net. The content of the json file is:
[
[ "240521000", "37.46272", "25.32613", "0", "71", "90", "15", "2016-07-18T21:09:00" ],
[ "237485000", "37.50118", "25.23968", "177", "211", "273", "8", "2015-09-18T21:08:00" ]
]
I created the following code:
WebClient wc = new WebClient();
string json = wc.DownloadString("data.json");
dynamic myObject = JsonConvert.DeserializeObject<dynamic>(json);
foreach (string item in myObject[0])
{
var x = item[0];
}
How can I loop through all the individual items without having a key?
You probably just need two nested foreach statements. Try something like this:
foreach (var items in myObject)
{
foreach (var item in items)
{
// do something
}
}
While diiN_'s answer answers the question, I don't think it's a good solution. Having had a look at the Marine Traffic API, it feels like they've made a poor JSON implementation, as the XML representation clearly has attribute names for the values. Their JSON should've been:
{"positions": ["position": {"mmsi": "311029000", "lat": "37.48617", "long": "24.37233", ...}]}
Because it isn't, we have a JSON string instead where it's a nested array, where the array is a two-dimensional array, and you'd have to hope the data model isn't changed to remove something, as you'd have to use an index to retrieve data.
However, if you look at the XML available from the API, the attributes have names. I would suggest that you instead download the XML, and parse this into an object - a model, in ASP.NET - which is strongly typed, and can be used more easily in a View.
Here's an example that I've got running. It uses XML parsing to first read the XML from the API, and then parse it to JSON, and finally an actual object.
First, the model class (Position.cs)
public sealed class Position
{
[JsonProperty("#MMSI")]
public string MMSI { get; set; }
[JsonProperty("#LAT")]
public string Latitude { get; set; }
[JsonProperty("#LON")]
public string Longitude { get; set; }
[JsonProperty("#SPEED")]
public string Speed { get; set; }
[JsonProperty("#HEADING")]
public string Heading { get; set; }
[JsonProperty("#COURSE")]
public string Course { get; set; }
[JsonProperty("#STATUS")]
public string Status { get; set; }
[JsonProperty("#TIMESTAMP")]
public string TimeStamp { get; set; }
}
Next, the parsing logic:
var client = new WebClient();
var xml = client.DownloadString("data.xml");
var doc = new XmlDocument();
doc.LoadXml(xml);
var json = JsonConvert.SerializeXmlNode(doc);
var positions = JObject.Parse(json).SelectToken("pos").SelectToken("row").ToObject<List<Position>>();
At the end of the parsing logic, you now have a list of Positions which you can pass to your view, and have it be strongly typed.
As a brief example:
// after you have the positions list
return View(positions);
Positions.cshtml
#model List<Positions>
<h2>Positions</h2>
#foreach (var position in Model)
{
<p>#position.MMSI (#position.Latitude, #position.Longitude)</p>
}
I hope this is useful to you. If you have any questions, drop me a comment.
Related
Serialize JSON with numbers as property names
How can I serialize a DataTable which contains a list of phone numbers, BodyOverride and ChannelType to this structure? The final JSON should look like the sample below. I see some posts that suggest using a Dictionary, but not I'm not sure if I can achieve this. { "Addresses": { "+1713XXXXXXX": { "BodyOverride": "sent", "ChannelType": "SMS" }, "+1832XXXXXXX": { "BodyOverride": "this is a text from PINPOINT", "ChannelType": "SMS" } } }
Try a using class structure like this: public class Payload { public Dictionary<string, Item> Addresses { get; set; } } public class Item { public string BodyOverride { get; set; } public string ChannelType { get; set; } } Assuming you are starting from a DataTable that looks like this: DataTable dataTable = new DataTable(); dataTable.Columns.Add("Address"); dataTable.Columns.Add("BodyOverride"); dataTable.Columns.Add("ChannelType"); dataTable.Rows.Add("+1713XXXXXXX", "sent", "SMS"); dataTable.Rows.Add("+1832XXXXXXX", "this is a text from PINPOINT", "SMS"); ...you can easily convert it to the desired class structure like this: var payload = new Payload { Addresses = dataTable.Rows .Cast<DataRow>() .ToDictionary(row => (string)row["Address"], row => new Item { BodyOverride = (string)row["BodyOverride"], ChannelType = (string)row["ChannelType"] }) }; ...and finally serialize it to JSON using a decent serialization library like Json.Net: string json = JsonConvert.SerializeObject(payload, Formatting.Indented); Fiddle: https://dotnetfiddle.net/b7Ckzs Important note: the above solution assumes that the phone numbers in the Address column will be distinct across all rows in the DataTable. If they are not, then this solution will not work, because dictionary keys are required to be unique. In that case you will need to split the data into multiple batches, or find some other solution to deal with duplicates.
c# multi level json
I am trying to make a simple program that can automate price checking using data from json, however I haven't used json before and I'm not quite sure what I need to do get get the desired result. Effectively I'm trying to convert this PHP into c#. (http://www.sourcecodester.com/tutorials/php/8042/api-json-parsing-php.html) <?php $src = file_get_contents('https://www.g2a.com/marketplace/product/auctions/?id=256'); $json = json_decode($src, true); foreach ($json as $k=>$v) { if (is_array($v)) { foreach($v as $key=>$value) { if (is_array($value)) { foreach($value as $arKey => $arValue) { if ($arKey == 'p') { echo $arValue . '<br/>'; } } } } } } ?> I've tried a few things such as JsonConvert.DeserializeObject(webJson) and JObject.Parse(webJson), but I'm just not sure where I should be looking or how to go about doing it. I have the first part: internal static string GetWebContent(string #ID) { var wc = new WebClient(); string response = wc.DownloadString(#"https://www.g2a.com/marketplace/product/auctions/?id=" + #ID); return response; } A response looks like this: (https://www.g2a.com/marketplace/product/auctions/?id=27446) {"a":{"k_709942":{"c":"pl","tr":3451,"f":"\u00a324.71","fb":"\u00a327.18","ci":"565784","cname":"Marketplace User","p":"24.7098173","pb":"27.18431394","ep":"35.15","epb":"38.67","a":"709942","it":"game","t":"1","sl":"0","l":null,"lt":null,"x":0,"v":"all","so":0,"r":99},"k_763218":{"c":"pl","tr":1120,"f":"\u00a324.74","fb":"\u00a327.22","ci":"6533797","cname":"User #f36726dcd","p":"24.7449664","pb":"27.21946304","ep":"35.20","epb":"38.72","a":"763218","it":"game","t":"0","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":92},"k_799750":{"c":"pl","tr":559,"f":"\u00a324.78","fb":"\u00a327.26","ci":"6115711","cname":"Marketplace User","p":"24.7801155","pb":"27.26164196","ep":"35.25","epb":"38.78","a":"799750","it":"game","t":null,"sl":"0","l":null,"lt":null,"x":0,"v":"retail","so":0,"r":98},"k_722082":{"c":"gb","tr":49066,"f":"\u00a324.96","fb":"\u00a327.45","ci":"1047917","cname":"Marketplace User","p":"24.955861","pb":"27.4514471","ep":"35.50","epb":"39.05","a":"722082","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":98},"k_718113":{"c":"pl","tr":5852,"f":"\u00a324.96","fb":"\u00a327.45","ci":"226876","cname":"Marketplace User","p":"24.955861","pb":"27.4514471","ep":"35.50","epb":"39.05","a":"718113","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":98},"k_739155":{"c":"pl","tr":1208,"f":"\u00a325.43","fb":"\u00a327.98","ci":"6540559","cname":"User #1f948a6a66249","p":"25.43316468854","pb":"27.976481157394","ep":"35.30","epb":"38.83","a":"739155","it":"game","t":"0","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":89},"k_795049":{"c":"pl","tr":50420,"f":"\u00a325.86","fb":"\u00a328.45","ci":"2498689","cname":"Marketplace User","p":"25.86270778","pb":"28.44968154","ep":"36.79","epb":"40.47","a":"795049","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":99},"k_816132":{"c":"pl","tr":22,"f":"\u00a326.00","fb":"\u00a328.60","ci":"6208533","cname":"Marketplace User","p":"25.99627436","pb":"28.59730776","ep":"36.98","epb":"40.68","a":"816132","it":"game","t":"0","sl":"0","l":null,"lt":"0","x":0,"v":"retail","so":0,"r":0},"k_809925":{"c":"pl","tr":81021,"f":"\u00a326.00","fb":"\u00a328.60","ci":"407513","cname":"Marketplace User","p":"26.00330418","pb":"28.60433758","ep":"36.99","epb":"40.69","a":"809925","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"retail","so":0,"r":100},"k_815898":{"c":"cl","tr":1,"f":"\u00a326.01","fb":"\u00a328.61","ci":"7524623","cname":"Marketplace User","p":"26.010334","pb":"28.6113674","ep":"37.00","epb":"40.70","a":"815898","it":"game","t":null,"sl":"0","l":null,"lt":null,"x":0,"v":"retail","so":0,"r":0},"k_711901":{"c":"pl","tr":12194,"f":"\u00a326.51","fb":"\u00a329.16","ci":"286793","cname":"Marketplace User","p":"26.506689203722","pb":"29.158078610346","ep":"36.79","epb":"40.47","a":"711901","it":"game","t":"1","sl":"0","l":null,"lt":null,"x":0,"v":"all","so":0,"r":99},"k_748710":{"c":"pt","tr":66460,"f":"\u00a326.65","fb":"\u00a329.32","ci":"440288","cname":"Marketplace User","p":"26.650786454082","pb":"29.316585585742","ep":"36.99","epb":"40.69","a":"748710","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":100},"k_709464":{"c":"pl","tr":121341,"f":"\u00a327.02","fb":"\u00a329.72","ci":"1072530","cname":"User #3285e5f8dfcb2","p":"27.0182344425","pb":"29.72005788675","ep":"37.50","epb":"41.25","a":"709464","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"retail","so":0,"r":100},"k_709805":{"c":"pl","tr":11708,"f":"\u00a328.09","fb":"\u00a330.90","ci":"1043113","cname":"User #ca1965d0354a","p":"28.091758957682","pb":"30.901655339702","ep":"38.99","epb":"42.89","a":"709805","it":"game","t":"1","sl":"0","l":null,"lt":null,"x":0,"v":"retail","so":0,"r":100},"k_725839":{"c":"es","tr":1,"f":"\u00a331.99","fb":"\u00a335.18","ci":"7023396","cname":"Marketplace User","p":"31.985681","pb":"35.1842491","ep":"45.50","epb":"50.05","a":"725839","it":"game","t":null,"sl":"0","l":null,"lt":null,"x":0,"v":"retail","so":0,"r":0},"k_0":{"f":"\u00a332.33","fb":"\u00a335.56","p":"32.33014218","pb":"35.563156398","ep":"45.99","epb":"50.59","a":0,"c":"","rc":"","r":"","tr":0,"t":1,"so":0,"x":0,"n":"G2A.com"}},"w":0} Any help with will greatly appreciated. Thanks in advace
So Json is a way for two languages to pass objects to each other. It's just a way to encode an object, so the first part would be to create an object that matches the Json encoding. I was unable to see your example, so I will give you one of my own. {"Aggregates": [{"ColumnName": "Some Value", "AggregateFunction": "Some Other Value"}], "GroupBy": true} I would then create a class like this one. public class JsonAggregates { public List<Aggregate> Aggregates { get; set; } public string GroupBy { get; set; } } public class Aggregate { public string ColumnName {get; set;} public string AggregateFunction {get; set;} } You can then encode the Json to this new data type with the following code. using (Stream s = GenerateStreamFromString(json)) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(JsonAggregates)); JsonAggregates aggregate = (JsonAggregates)serializer.ReadObject(s); }
Dealing with fanart.tv webservice response JSON and C#
I am trying to use the fanart.tv webservice API but have a couple of issues. I am using Json.Net (Newtonsoft.Json) and with other web-services I have de-serialized the JSON reponses into C# objects directly. The issue here is that the element names are changing. Eg. if I search for artist thumbs for Metallica you get {"Metallica":{"mbid_id":"65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab","artistthumb": [{"id":"36181","url":"http://assets.fanart.tv/fanart/music/65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab/artistthumb/metallica-4fd83b0129f83.jpg","likes":"1"},...]}} So the root element is called Metallica. Obviously search for another artist and you get a different element name. After attempting to deserialize this to an object I gave up and as in reality all I needed was a list of strings (the urls) I tried to process the JSON var obj = _downloader.Download<JObject>(url); if (obj != null) { if (obj.HasValues) { var fanartArtist = (JProperty)obj.First; if (fanartArtist.HasValues) { var thumbs = fanartArtist.Value[SearchSubTypeToString(subType)]; if (thumbs.HasValues) { thumbUrls.AddRange(thumbs.Select(thumb => thumb["url"].ToString())); } } } } which works fine when there is a response but if there are no thumbs the web-service returns null and this code fails with Unable to cast object of type 'Newtonsoft.Json.Linq.JValue' to type 'Newtonsoft.Json.Linq.JObject'. To complicate matters slightly I am sort of limited by the application and ideally I need to use JsonConvert.DeserializeObject<TE>(json); So the question is what what is the best approach to solve both of these issues?
Try this: First, define objects to hold the data deserialized from the JSON: class Artist { public Guid mb_id { get; set; } public List<Thumb> artistthumb { get; set; } } class Thumb { public int id { get; set; } public string url { get; set; } public int likes { get; set; } } You can then deserialize it like this (where json is a string containing the JSON data from the web service): Dictionary<string, Artist> artists = JsonConvert.DeserializeObject<Dictionary<string, Artist>>(json); Once deserialized, you can access the data like this: foreach (KeyValuePair<string, Artist> kvp in artists) { Console.WriteLine("Urls for " + kvp.Key + ":"); foreach (Thumb thumb in kvp.Value.artistthumb) { Console.WriteLine(thumb.url); } } Assuming the data you showed in your question, the output would look like this: Urls for Metallica: http://assets.fanart.tv/fanart/music/65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab909e7ae6b2ab/artistthumb/metallica-4fd83b0129f83.jpg .
Alter Json or ExtensionDataObject
I have a Json service I cannot alter as it is not mine. Their Json is a formatted in a way that parsing it is difficult. It looks something like this. "people": { "Joe Bob": { "name": "Joe Bob", "id": "12345" }, "Bob Smith": { "name": "Bob Smith", "id": "54321" } }, I would really prefer this was laid out like a JSon array, however it presently is not. I am wondering the best approach here. Should I alter the Json to look like an array before I parse it or load up the ExtensionData and parse it from that? There are other items in the feed that I do not have issue with. Just stuck with this one section. Thanks
You can use json.net to deserialize the data (the json you pasted, and doing only one parsing, without modifying anything). using dynamic foo = JsonConvert.DeserializeObject<dynamic>(data) than, you can iterate the list using foo.people, accessing the Name and Value. you can create a class (if you know what the schema is, and to deserialize the data into a list of the given class such as: public class People { [JsonProperty(PropertyName="people")] public IDictionary<string, Person> Persons { get; set; } } public class Person { [JsonProperty(PropertyName="name")] public string Name { get; set; } [JsonProperty(PropertyName = "id")] public string Id { get; set; } } and than call: var obj = JsonConvert.DeserializeObject<People>(data); foreach (var item in obj.Persons.Values) { //item is instance of Person } Another good and possible option will be: How can I navigate any JSON tree in c#?
Convert json to a C# array?
Does anyone know how to convert a string which contains json into a C# array. I have this which reads the text/json from a webBrowser and stores it into a string. string docText = webBrowser1.Document.Body.InnerText; Just need to somehow change that json string into an array. Been looking at Json.NET but I'm not sure if that's what I need, as I don't want to change an array into json; but the other way around. Thanks for the help!
just take the string and use the JavaScriptSerializer to deserialize it into a native object. For example, having this json: string json = "[{Name:'John Simith',Age:35},{Name:'Pablo Perez',Age:34}]"; You'd need to create a C# class called, for example, Person defined as so: public class Person { public int Age {get;set;} public string Name {get;set;} } You can now deserialize the JSON string into an array of Person by doing: JavaScriptSerializer js = new JavaScriptSerializer(); Person [] persons = js.Deserialize<Person[]>(json); Here's a link to JavaScriptSerializer documentation. Note: my code above was not tested but that's the idea Tested it. Unless you are doing something "exotic", you should be fine using the JavascriptSerializer.
using Newtonsoft.Json; Install this class in package console This class works fine in all .NET Versions, for example in my project: I have DNX 4.5.1 and DNX CORE 5.0 and everything works. Firstly before JSON deserialization, you need to declare a class to read normally and store some data somewhere This is my class: public class ToDoItem { public string text { get; set; } public string complete { get; set; } public string delete { get; set; } public string username { get; set; } public string user_password { get; set; } public string eventID { get; set; } } In HttpContent section where you requesting data by GET request for example: HttpContent content = response.Content; string mycontent = await content.ReadAsStringAsync(); //deserialization in items ToDoItem[] items = JsonConvert.DeserializeObject<ToDoItem[]>(mycontent);
Yes, Json.Net is what you need. You basically want to deserialize a Json string into an array of objects. See their examples: string myJsonString = #"{ "Name": "Apple", "Expiry": "\/Date(1230375600000+1300)\/", "Price": 3.99, "Sizes": [ "Small", "Medium", "Large" ] }"; // Deserializes the string into a Product object Product myProduct = JsonConvert.DeserializeObject<Product>(myJsonString);
Old question but worth adding an answer if using .NET Core 3.0 or later. JSON serialization/deserialization is built into the framework (System.Text.Json), so you don't have to use third party libraries any more. Here's an example based off the top answer given by #Icarus using System; using System.Collections.Generic; namespace ConsoleApp { class Program { static void Main(string[] args) { var json = "[{\"Name\":\"John Smith\", \"Age\":35}, {\"Name\":\"Pablo Perez\", \"Age\":34}]"; // use the built in Json deserializer to convert the string to a list of Person objects var people = System.Text.Json.JsonSerializer.Deserialize<List<Person>>(json); foreach (var person in people) { Console.WriteLine(person.Name + " is " + person.Age + " years old."); } } public class Person { public int Age { get; set; } public string Name { get; set; } } } }
One Situation that wasn't covered in the other responses is when you don't know the type of what the JSON object contains. That was my case as I needed to be able to NOT type it and leave it dynamic. var objectWithFields = js.Deserialize<dynamic[]>(json); Note: it is definitely preferred to have a type, in some cases, it is not possible, that's why I added this answer.