This question already has answers here:
How can I parse a JSON string that would cause illegal C# identifiers?
(3 answers)
Create a strongly typed c# object from json object with ID as the name
(1 answer)
How can I deserialize JSON with C#?
(19 answers)
Closed 4 years ago.
I'm fairly new to json, and I'm trying to convert some json content to a C# class to store it for later use. I'm having a problem trying to create a class which is suitable for the data structure. An example of the json content is shown below.
Json Data
{
"FirstItem": {
"id": 1,
"type": "foo",
"colours": ["blue", "black", "green"],
"reviews": {
"positive": ["The best", "unbelievable", "Awesome"],
"negative": ["Sh*t", "Awful", "Dire", "Terrible", "Appalling"],
"neutral": ["OK", "Meh"]
}
},
"SecondItem": {
"id": 2,
"type": "bar",
"colours": ["red", "white", "yellow"],
"reviews": {
"positive": ["Great", "Amazing", "Fantastic", "Perfect", "Uplifting"],
"negative": ["Terrible", "Shocking", "abysmal"],
"neutral": ["OK", "Standard", "Vanilla"]
}
}
}
Edit:
It's worth noting that this is just a small sample of the json data, and I expect to be working with a much larger data set which is always in this format, however the FirstItem, SecondItem (names?) will always be different. I could potentially end up with a MillionthItem.
C# Class
I have created a class based on my limited understanding of the json data above. I think this is where the problem lies - I dont think this class is suitable based on the json above. Here's what I have.
public class Data
{
public string name {get; set;}
public int id {get; set;}
public string type {get; set;}
public string[] colours {get; set;}
public Reviews reviews {get; set;}
}
public class Reviews
{
public string[] positive {get; set;}
public string[] negative {get; set;}
public string[] neutral {get; set;}
}
Converting json to class
To try and convert this, I am using JsonConvert to deserialize the data to a List of a class which I have created. For example:
var client = new RestClient(url);
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
var result = JsonConvert.DeserializeObject<List<Data>>(response.Content);
Exception
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[namespace.class]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Summary
I'd appreciate some advice on understanding the json format above, and how I can successfuly convert this
Solution
dbc suggested storing this information in a dictionary, which was exactly what I was needing to do - this allows me to capture the name (FirstItem, SecondItem etc.) as the key and the rest of the class Data as the value.
var result = JsonConvert.DeserializeObject<Dictionary<string, Data>>(response.Content);
Just copy your json and do Edit->Paste Special->Paste Json As Classes in Visual Studio - it will create you the matching class structure.
public class Rootobject
{
public Firstitem FirstItem { get; set; }
public Seconditem SecondItem { get; set; }
}
public class Firstitem
{
public int id { get; set; }
public string type { get; set; }
public string[] colours { get; set; }
public Reviews reviews { get; set; }
}
public class Reviews
{
public string[] positive { get; set; }
public string[] negative { get; set; }
public string[] neutral { get; set; }
}
public class Seconditem
{
public int id { get; set; }
public string type { get; set; }
public string[] colours { get; set; }
public Reviews1 reviews { get; set; }
}
public class Reviews1
{
public string[] positive { get; set; }
public string[] negative { get; set; }
public string[] neutral { get; set; }
}
Then usage will be like:
var rootObject = JsonConvert.DeserializeObject<Rootobject>(jsonString);
Related
I am reading 2 REST APIs using Httpclient in C#. The APIs return following employee data in JSON format:
1st API
{
"status": "OK",
"content": {
"empid1": 89900,
"empid2": 45550,
"empid3": 22350}
}
2nd API
{
"status": "OK",
"content": {
"empid1": "grade1",
"empid1": "grade2",
"empid1": "grade2"}}
Classes defined and code used is as follows:
public class content
{
public string empid { get; set; } // e.g. empid3
public double salary { get; set; } // e.g. 89900
public string grade { get; set; } // e.g. Grade1
}
public sealed class WrapperEmployees
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("data")]
public List<content> empdata { get; set; } = new List<data>();
}
To deserialize, used this-
WrapperEmployees nj = JsonConvert.DeserializeObject<WrapperEmployees>(response);
But, last line gives error on deserialization:
Cannot deserialize current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[CsharpSample.App_Code.Employee]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'content.emp1', line 4, position 18.
Is my class structure incorrect?
My ultimate aim is to fetch common data from both APIs against employees.
Option 1: use specific classes for each json deserialization:
class EmployeesSalaries {
public string Status { get; set; }
public Dictionary<string, int> content { get; set; };
}
class EmployeesGrades {
public string Status { get; set; }
public Dictionary<string, string> content { get; set; };
}
Option 2: deserialize to common class, but you will get 'good' content values only if they are int/string. If they will be objects - you will have JObjects as values.
class EmployeesData {
public string Status { get; set; }
public Dictionary<string, object> content { get; set; };
}
.Net Fiddle 1
I have a JOSN received from external API as follows
[{
"assignedto": "MAIN STAFF",
"createduser": "API-71",
"departmentid": "1",
"observations": [{
"abnormalflag": "abnormal",
"analytename": "HGB A1C",
"value": "5"
}],
"pages": [],
"priority": "2",
"status": "REVIEW"
}]
I did a Paste Special in Visual Studio and got following classes
public class Rootobject
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public string assignedto { get; set; }
public string createduser { get; set; }
public string departmentid { get; set; }
public Observation[] observations { get; set; }
public object[] pages { get; set; }
public string priority { get; set; }
public string status { get; set; }
}
public class Observation
{
public string abnormalflag { get; set; }
public string analytename { get; set; }
public string value { get; set; }
}
When I do a deserialization, I am getting following error
Run-time exception (line 24): Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Rootobject' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '', line 1, position 1.
C# Code
public static void Main(string[] args)
{
var json = #"[{
""assignedto"": ""MAIN ST (HUB) STAFF"",
""createduser"": ""API-7127"",
""departmentid"": ""1"",
""observations"": [{
""abnormalflag"": ""abnormal"",
""analytename"": ""HGB A1C"",
""value"": ""5""
}],
""pages"": [],
""priority"": ""2"",
""status"": ""REVIEW""
}]";
Rootobject resultObj = JToken.Parse(json).ToObject<Rootobject>();
}
I referred similar questions like Create a strongly typed c# object from json object with ID as the name - but that is a different issue.
Any idea how to fix this? Also what is the better way to generate C# classes from JSON?
Note: I also tried with class I got from http://json2csharp.com/. That also faield - Fidlle 2
I would use Newtonsoft / Json convert and change this:
Rootobject resultObj = JToken.Parse(json).ToObject<Rootobject>();
to:
using Newtonsoft.Json;
-- snip --
var resultObj = JsonConvert.DeserializeObject<List<Class1>>(json);
Console.WriteLine(resultObj.Count); // 1
Class1 result = resultObj[0];
Console.WriteLine(result.assignedto); // "MAIN ST (HUB) STAFF"
This will give you a collection of RootObject
As #JeffMeracdo states above - you are providing a collection of object and trying to parse as though it is a single object
As #JeffMeracdo states above, try this:
List<Example> resultObj = JsonConvert.DeserializeObject<List<Example>>(json);
Following using statement and package along with Newtonsoft.Json Nuget package:
using Newtonsoft.Json;
Classes:
public class Observation
{
public string abnormalflag { get; set; }
public string analytename { get; set; }
public string value { get; set; }
}
public class Example
{
public string assignedto { get; set; }
public string createduser { get; set; }
public string departmentid { get; set; }
public List<Observation> observations { get; set; }
public List<object> pages { get; set; }
public string priority { get; set; }
public string status { get; set; }
}
I am getting JSON that is being returned from a REST web service for survey responses. It has arrays for the name portion of some of the name value pairs. Additionally the names will be variable depending on the type of questions asked. I'm using JSON.net and trying to deserialize the returned value into some type of object tree that I can walk but can't figure out what structure to use to have it filled in.
I tested the following snippet in LinqPad and fields is always empty. Is there someway to easily read in the variable data or do I have to parse it in code?
void Main() {
string json = #"{
'result_ok':true,
'total_count':'51',
'data':[{
'id':'1',
'status':'Deleted',
'datesubmitted':'2015-01-12 10:43:47',
'[question(3)]':'Red',
'[question(4)]':'Blue',
'[question(18)]':12,
'[variable(\'STANDARD_IP\')]':'127.0.0.1',
'[variable(\'STANDARD_GEOCOUNTRY\')]':'United States'
}]
}";
var responses = JsonConvert.DeserializeObject<RootObject>(json);
responses.Dump();
}
public class RootObject {
public bool result_ok { get; set; }
public string total_count { get; set; }
public List<Response> data { get; set; }
}
public class Response {
public string id { get; set; }
public string status { get; set; }
public string datesubmitted { get; set; }
public List<object> fields = new List<object>();
}
Change the fields property in your Response class to be a Dictionary<string, object>, then mark it with a [JsonExtensionData] attribute like this:
public class Response
{
public string id { get; set; }
public string status { get; set; }
public string datesubmitted { get; set; }
[JsonExtensionData]
public Dictionary<string, object> fields { get; set; }
}
All of the fields with the strange property names will then be placed into the dictionary where you can access them as normal. No extra code is required.
Here is a demo: https://dotnetfiddle.net/1rQUXT
I am trying to deserialise a json object. The Problem is that the the object also contains subarrays
http://i.imgur.com/WWwEVLR.png
Except for the subarrays everything is working.
I am using Newtonsoft.Json;
Here is my class
public string date_updated { get; set; }
public string date_expires { get; set; }
This is working fine.
For the subarray I did it that way:
public JsonArray contacts { get; set; }
This is my method to deserialise it:
var json = await webClient.GetAsync(new Uri(uri));
var result = await json.Content.ReadAsStringAsync();
Model = JsonConvert.DeserializeObject<Model>(result);
The Array is created well with all fields needed, but the values are not working.
The values are just: Windows.Json.JsonObject as on the picture below.
http://i.imgur.com/Q8bpCoD.png
Why is he not writing the values? How can I get them?
Thank you for your help.
The values are working fine. Using JsonArray tells the deserializer to convert the JSON data to something that is compatible with the type JsonArray. This type is simply a 1:1 representation of the JSON string underneath and is not deserialized into useful data automatically for you.
Also, JsonArray is not even part of the Json.Net library. As the debugger is telling you, it is part of the Windows.Data.Json namespace which is in a different library. You could still access the data directly from each JsonObjects using the various Get methods inside the class ( http://msdn.microsoft.com/en-us/library/windows.data.json.jsonobject.aspx ) but this is probably not the way you want to go.
In your case, you should create a class that represents the data you have inside each of those arrays. If not all entries in the array contains all of the properties of your class, don't worry. Json.Net will simply leave their value empty when deserializing. This will look like:
public class Contact
{
public string type { get; set; }
public string name { get; set; }
public string organization { get; set; }
public string full_address { get; set; }
etc.
}
For good measure, you should also respect the C# naming convention which states that properties should use CamelCase names. To help you with this, you can use the JsonProperty attribute like so:
public class Contact
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("organization")]
public string Organization { get; set; }
[JsonProperty("full_address")]
public string FullAddress { get; set; }
etc.
}
Then, you can replace the type of your contacts property to List<Contact> and the data will be automatically deserialized to a format that you can easily use.
Define new class
class Contact {
public string type { get; set; }
public string name { get; set; }
// etc
}
and modify your ReqInfo_WhoIs_Model class
public string date_updated { get; set; }
public string date_expires { get; set; }
public List<Contact> contacts { get; set; }
I just started dabbling with C#, and I've been banging my head over JSON deserialization for a while now. I'm using Newtonsoft.Json library. I'm expecting just a json response of an array of dictionaries as such
[{"id":"669","content":" testing","comments":"","ups":"0","downs":"0"}, {"id":"482","content":" test2","comments":"","ups":"0","downs":"0"}]
Right now I have: (note: download is just a string holding the json string)
string[] arr = JsonConvert.DeserializeObject<string[]>(download);
I've tried many different ways of doing this, each failed. Is there a standard way for parsing json of this type?
You have an array of objects not strings. Create a class that maps the properties and deserialize into that,
public class MyClass {
public string id { get; set; }
public string content { get; set; }
public string ups { get; set; }
public string downs { get; set; }
}
MyClass[] result = JsonConvert.DeserializeObject<MyClass[]>(download);
There are only a few basic types in JSON, but it is helpful to learn and recognize them. Objects, Arrays, strings, etc. http://www.json.org/ and http://www.w3schools.com/json/default.asp are good resources to get started. For example a string array in JSON would look like,
["One", "Two", "Three"]
I implement this and hope this is helpful all.
var jsonResponse =
[{"Id":2,"Name":"Watch"},{"Id":3,"Name":"TV"},{"Id":4,"Name":""}]
var items = JsonConvert.DeserializeObject<List<MyClass>>(jsonResponse);
where MyClass is the entity
public class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
}