C# Deserialize JSON array - c#

I am having an issue deserializing and defining this JSON structure would be great to get some assistance. I have reverted this back to last known working position because I am just going off the rails here.
my JSON stucture is:
[{
"name": "Name1",
"description": "Description of this process",
"Location": "ANY",
"SubItems": [{
"name": "sub1",
"required": true,
"description": "This is a short description"
}, {
"name": "sub2",
"required": true,
"description": "This is a short description"
}, {
"name": "sub3",
"required": true,
"description": "This is a short description"
}],
"outputs": [{
"name": "out1",
"required": false
}, {
"name": "exit code",
"required": false
}]
}, {
"name": "Name2",
"description": "This is a short description",
"Location": "ANY",
"SubItems": [{
"name": "sub1",
"required": false,
"description": "This is a short description"
}]
}]
Here are my C# Json definitions that were last working.
public class JsonObject
{
[JsonProperty("name")]
public string ProcessName { get; set; }
[JsonProperty("description")]
public string ProcessDescription { get; set; }
[JsonProperty("Location")]
public string KnownLocation { get; set; }
}
I am only capturing a couple of definitions at the moment for testing.
Here is my deserializing object
var Object = JsonConvert.DeserializeObject <List<JsonObject>>(txt);
foreach (JsonObject JsonObject in Object)
{
Console.WriteLine("Name: " + JsonObject.ProcessName);
Console.WriteLine();
Console.WriteLine("Description: " +JsonObject.ProcessDescription);
Console.WriteLine();
}
So as I had stated, I can get at least the first 3 top-most level JSON elements in the output. The problem starts when I start trying to get the "SubItems" and "outputs"
I followed the structure of the below linked post and tried very hard to understand it, but after a while I realized that solution is not for this issue. I simply have a multi-dimentional array JSON object. Literally has a top tier, and 2 sub tiers
I attempted to try and do...
List<List<JsonObject>>Object = JsonConvert.DeserializeObject <List<List<JsonObject>>>(txt);
and tried to have 2 lists of the same with different names with 3 sets of JSON Definitions.
and implemented the tiered foreach loops, but then I wasn't able to access the definitions for the top most JSON, and nothing was writing for the actual elements for "SubItems"
What I need is to get to each object, really.
How to deserialize a json file with multidimensional array to convert it to object in c#
Related Issue

It is not a multi dimentional array. Just an array objects containing arrays.
So your model can be as follows
public class SubItem
{
public string Name { get; set; }
public bool Required { get; set; }
public string Description { get; set; }
}
public class Output
{
public string Name { get; set; }
public bool Required { get; set; }
}
public class JsonObject
{
public string Name { get; set; }
public string Description { get; set; }
public string Location { get; set; }
public List<SubItem> SubItems { get; set; }
public List<Output> Outputs { get; set; }
}
and you can deserialize as
var obj = JsonConvert.DeserializeObject<List<JsonObject>>(jsonstring);
PS: you can use JsonProperty to decorate that model as you do in question

Related

I want to convert api json data to value c#

Hi i'm newbie in c# dev and i'm not good at english i try to get value from json but it gives error [https://www.tutorialsteacher.com/articles/convert-json-string-to-object-in-csharp]
If anyone can help me with simple code I would be very grateful.
{
"result": [{
"company": "Server",
"results": [{
"name": "Server-01",
"access": ["8.8.8.8:443", "1.1.1.1:443"],
"is_ok": "0"
}, {
"name": "Server-02",
"access": ["8.8.8.8:443", "1.1.1.1:443"],
"is_ok": "0"
}, {
"name": "Server-03",
"access": ["8.8.8.8:443", "1.1.1.1:443"],
"is_ok": "1"
}, {
"name": "Server-04",
"access": ["8.8.8.8:443", "1.1.1.1:443"],
"is_ok": "0"
}, {
"name": "Server-05",
"access": ["8.8.8.8:443", "1.1.1.1:443"],
"is_ok": "0"
}]
}]
}
C# can be different. Like .Net Framework or .Net Core / .Net, so next time please provide which framework do you use.
The are two common ways to deserialize JSON string - Json.NET (3rd party) or System.Text.Json (part of .Net).
For correct deserealization first of all you must provide valid models. But sometimes JSON properties violates C# Naming Conventions or they even can't be represented in code (e.g. property name with whitespace or "is_ok" from your JSON). To avoid this you must to use property attribute that connect your property in code and property in JSON. It's:
[JsonProperty("PropertyName")] for Json.NET
[JsonPropertyName("PropertyName")] for System.Text.Json
So, summing up the above, you must add models similar to this:
public class ResultWrapper
{
[JsonProperty("result")] //use one of it based on selected library
[JsonPropertyName("result")]
public List<Result> Result { get; set; }
}
public class Result
{
[JsonProperty("company")]
[JsonPropertyName("company")]
public string Company { get; set; }
[JsonProperty("results")]
[JsonPropertyName("results")]
public List<ResultItem> Results { get; set; }
}
public class ResultItem
{
[JsonProperty("name")]
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonProperty("access")]
[JsonPropertyName("access")]
public List<string> Access { get; set; }
[JsonProperty("is_ok")]
[JsonPropertyName("is_ok")]
public string IsOk { get; set; }
}
and use one of next deserealization methods:
//Json.Net
var deserializedJsonNet = JsonConvert.DeserializeObject<ResultWrapper>(jsonFromQuestion);
//System.Text.Json
var deserializedSystemTextJson = JsonSerializer.Deserialize<ResultWrapper>(jsonFromQuestion);

JSON int array to DataContract array

im having trouble translating a json response from google's apis to DataContract classes. Specifically when trying to translate an int array from JSON to an int array in the DataContract.
Heres what I have done so far.
Heres the JSON response.
{
"kind": "youtubeAnalytics#resultTable",
"columnHeaders": [
{
"name": "views",
"columnType": "METRIC",
"dataType": "INTEGER"
},
{
"name": "likes",
"columnType": "METRIC",
"dataType": "INTEGER"
},
{
"name": "dislikes",
"columnType": "METRIC",
"dataType": "INTEGER"
}
],
"rows": [
[
2162435,
871,
907
]
]
}
And heres my Data Contract classes
[DataContract]
public class AnalyticsData
{
[DataMember(Name = "kind")]
public string Kind { get; set; }
[DataMember(Name = "columnHeaders")]
public ColumnRows[] ColumnHeaders { get; set; }
[DataMember(Name = "rows")]
public int[][] rows { get; set; } //<--------
}
[DataContract]
public class ColumnRows
{
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "columnType")]
public string ColumnType { get; set; }
[DataMember(Name = "dataType")]
public string DataType { get; set; }
}
The problem I am having is translating the 'rows' element from the JSON doc into DataContract variables, as as shown in the AnalyticsData class in the int array 'rows'.
The error I get when debugging is
System.Runtime.Serialization.SerializationException: There was an error deserializing the object of type StudioWP8.AnalyticsData. Input string was not in a correct format. ---> System.FormatException: Input string was not in a correct format.
Use jsonconvert and it will be ok
[TestMethod]
public void test()
{
string json =
"{ \"kind\": \"youtubeAnalytics#resultTable\", \"columnHeaders\": [ { \"name\":\"views\", \"columnType\": \"METRIC\", \"dataType\": \"INTEGER\" }, { \"name\": \"likes\", \"columnType\": \"METRIC\", \"dataType\": \"INTEGER\" }, { \"name\": \"dislikes\", \"columnType\": \"METRIC\", \"dataType\":\"INTEGER\" } ], \"rows\": [ [ 2162435, 871,907 ] ]}";
AnalyticsData d = JsonConvert.DeserializeObject<AnalyticsData>(json);
}

c# How do I parse a non array array

I need to parse a jsonfile that has a structure like this:
"number": {
"1": {
"branch": null,
"build": 1,
"files": [
[
"zip",
"client",
"4d96d6e8f1543c5fa1184f4771ce16e2"
],
[
"zip",
"src",
"fd397591148fac49a7d57aafdccac6a3"
],
[
"zip",
"server",
"d7e1df9a91ded33be81ee8226b027c2f"
],
[
"txt",
"changelog",
"df98aec1a868ce99532c64f246387d55"
]
],
"jobver": "1.3.2",
"mcversion": "1.1",
"modified": 1328269373.0,
"version": "1.3.2.01"
},
"2": {
"branch": null,
"build": 2,
"files": [
[
"zip",
"server",
"80fbd5d837a5867c2dd7b7967e3aa2a9"
],
[
"zip",
"client",
"0cedb5e9844e490f877b6cf04601f929"
],
[
"txt",
"changelog",
"87e9fba9322e9dbc2ea482a2c3edeec6"
],
[
"zip",
"src",
"292d5596879bd13c159a2afe571ec5eb"
]
],
"jobver": "1.3.2",
"mcversion": "1.1",
"modified": 1328613907.0,
"version": "1.3.2.2"
}
(The entire json file can be found here: http://files.minecraftforge.net/maven/net/minecraftforge/forge/json)
I have figure out the internals, in the "1" and the externals that leads to this code part, however using the Json.NET library I can't figure out how to deal with the "1" and "2"s without writing a seperate class for each. I have over 1000 of these to parse trough, so I need some way that can do it relatively simple.
My current class for parsing looks something like this:
public class forgemaven
{
public string homepage { get; set; }
public string name { get; set; }
public List<Number> number { get; set; }
public string webpath { get; set; }
}
public class Number
{
public string branch { get; set; }
public int build { get; set; }
public List<String> files { get; set; }
public string jobver { get; set; }
public string mcversion { get; set; }
public string modified { get; set; }
public string version { get; set; }
}
Note: I removed some of the things, like the first 1000 lines of version/build, since they aren't needed and json.net seems fine with that.
I have tried parsing it with http://json2csharp.com/ sadly that crashes my webbrowser. I also tried the desktop version of it, but that give me almost a MB of classes, which again isn't optimal, since new builds are constantly added to this file, so I would have to change my structure all the time, and it would be horrible to use the data from here.
So for my question: How do I do this in a maintainable way?
Your problem is that {"1" : something, "2" ; something} is not a json array, it's a json map.
In .net, you will want to deserialize that to a Dictionary<int,TObject>. Then you can process it afterwards if it really should be a `List' or an array, but you can't do that while deserializing: you got bad json in the first place, you have to deal with it.
Here is a fiddle demonstrating the thing (with the json you gave and your own classes only very slightly modified: the files property is a List<List<string>> instead of a List<String>) using Json.Net : https://dotnetfiddle.net/feqFZd
You must replace
public List<Number> number { get; set; }
with
public Dictionary<int,Number> number { get; set; }

How to deserialize json string in windows phone?

I just got my json response as a string.My json is given below,
"code": 0,
"message": "success",
"students": {
"details":{
"hjeke": {
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good",
},
"Second": {
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad",
}
}
}
Like hjeke and Second there are many key value pairs,how can i deserialize my json using Newtonsoft.json
Try to understand my solution in your previous question
How to deserialize json data in windows phone?
Your first JSON in that question was good and simple to use.
JSON, where field names are unique not convinient to deserialize. So, you got problems such as public class Hjeke and public class Second for each instance, when you use code generator.
Use JSON-structure with list of students:
"code": 0,
"message": "success",
"students": [
{
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good",
},
{
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad",
}]
is good and flexible structure. Using this, you don't need to parse not obvious fields like
"details":{
"hjeke": {
and so on.
And work with them using classes, from my previous answer. The main idea - you need list of objects. public List<StudentDetails> students. Then, all students objects deserialized in List, which is easy to use.
As everybody mentioned your json seems to be very unflexible, huh.
You can extract the data you are interested in.
So this is your model:
public class StudentDetails
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
And this is how you can extract it:
var jsonObj = JObject.Parse(str);
// get JSON result objects into a list
var results = jsonObj["students"]["details"].Children().Values();
// serialize JSON results into .NET objects
var details = new List<StudentDetails>();
foreach (JToken result in results)
{
var st = result.ToString();
var searchResult = JsonConvert.DeserializeObject<StudentDetails>(st);
details.Add(searchResult);
}
I'm using a newtonsoft.json library here.
Your Response string has some mistakes man, its not a valid json
just small modification to be done as below:
{
"code": 0,
"message": "success",
"students": {
"details": {
"hjeke": {
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good"
},
"Second": {
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad"
}
}
}
}
you can make out the difference
Now Follow these steps:
1.Go to this link Json to C#
2.place your Json string there and generate C# class object
3.Now create this class in your solution
4.Now deserialize As below
var DeserialisedObject = JsonConvert.DeserializeObject<Your Class>(YourJsonString);
First, create the classes:
public class Hjeke
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
public class Second
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
public class Details
{
public List<Hjeke> hjeke { get; set; }
public List<Second> Second { get; set; }
}
public class Students
{
public List<Details> details { get; set; }
}
public class RootObject
{
public int code { get; set; }
public string message { get; set; }
public List<Students> students { get; set; }
}
After that, use JSON.NET to deserialize:
var deserialized = JsonConvert.DeserializeObject<Class1>(YourStringHere);
Do you have any influence over the json response? Details should probably be a JSONArray in this case, not an object with a varying amount of properties, since I assume that's what you mean is the issue here.

parsing Json using system.web.script.seriarilization or using json.net

json ="{
"data": [
{
"id": "1000",
"from": {
"name": "Anthony Waema",
"category": "message",
"id": "192"
},
"message": "this is the message",
"updated_time": "2001-05-06T19:34:15+0000",
"likes": {
"data": [
{
"id": "100001692250255",
"name": "\u00dcnal Turanl\u0131"
},
{
"id": "100001060078996",
"name": "S\u00e9f\u00e2 K\u00e2ql\u00e4Nn"
}]
},
{
"id": "10150186255753553",
"from": {
"name": "another name",
"category": "message",
"id": "100001"
},
"message": "this is the message",
"updated_time": "2001-04-06T19:34:15+0000",
"likes": {
"data": [
{
"id": "1002345",
"name": "\u00dcnal Turanl\u0131"
},
{
"id": "100234",
"name": "S\u00e9f\u00e2 K\u00e2ql\u00e4Nn"
}]
}
}
]
}";
public class Allstatus
{
public List<sdata> data { get; set; }
public scpaging paging { get; set; }
}
public class sdata
{
public string id { get; set; }
public sfrom from { get; set; }
public string message { get; set; }
public string updated_time {get; set;}
public List<likesdata> likes { get; set; }
}
public class likesdata
{
public string id{ get; set; }
public string name{ get; set; }
}
public class sfrom
{
public string name {get; set;}
public string category {get; set;}
public string id {get; set;}
}
JavaScriptSerializer ser = new JavaScriptSerializer();
page = ser.Deserialize<allstatus>(json);
foreach (sdata cd in page.data)
{
foreach(likesdata ld in cd.likes.data)
{
Console.WriteLine(ld.id+"\t"+ld.name);
}
}
problem:
I need to parse the json and retrieve likes data.
I can access "from" data but not "likes" data.. I get nullreference error when I do this. help needed here.. Thanks.
Edit2:
Referring https://gist.github.com/973510, its clear from the returned json, that if a particular facebook message doesnt have any likes, then the returned json doesnt contain a property called likes. Hence likes property of sdata object is null. Thats just how the server returns the data.
There are two ways you can deal with this. Either do a manual check whether likes is null. Or initialize the likes property in the sdata constructor. And initialize the likesdata list in the likesdatacollection constructor.
Code:
public class sdata
{
// other properties
public likedatacollection likes { get; set; }
public sdata()
{
likes = new likedatacollection();
}
}
public class likedatacollection
{
public List<likesdata> data { get; set; }
public likedatacollection()
{
data = new List<likesdata>();
}
}
This way, even if fb doesnt return any likes, the constructors will initialize the properties, so they will not be null. You can then check whether likes.data.Count > 0. If yes, then fb returned likes, else fb didnt return likes.
Edit1:
From the OP's comment, its clear that the json is properly formed. Meaning, the json is as retrieved from some server api. Therefore it is the sdata class that is the culprit. Please look at this gist for the full solution.
The short version. For the simplest case, your c# classes need to follow the exact same structure as your json. As per the json, data has a property called likes. the likes object has a property called data which is an array of objects with properties id and name.
So your c# class sdata should have a property called likes of type likesdatacollection. This class should have a property data of type List<likesdata>...
Off topic, people generally seem to prefer Json.Net ... so you may want to use that. The reason I use it is because I need it to work in a .Net 2.0 code base ...
You should try running your JSON through a validator like JSON Lint. That should help you find any JSON errors.

Categories