Deserialize JSON array into C# Structure with RestSharp - c#

I am dynamically taking different JSON structures into various C# structures, using RestSharp and IRestResponse<T> response = client.Execute<T>(request). But, one particular JSON result is giving me trouble, where it starts and ends with brackets...
My JSON starts and ends with "[" and "]" characters:
[
{
"first": "Adam",
"last": "Buzzo"
},
{
"first": "Jeffrey",
"last": "Mosier"
}
]
I've created this class structure:
public class Person
{
public string first { get; set; }
public string last { get; set; }
}
public class Persons
{
public List<Person> person { get; set; }
}
I use RestSharp within a method to deserialize dynamically into my Persons type T...
IRestResponse<T> response = client.Execute<T>(request);
return response;
The problem is that when T is Persons I get this error on the client.Execute line:
Unable to cast object of type 'RestSharp.JsonArray' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Object]'.
I also tried with Json.Net and got this error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Persons' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.
Given the initial "[" character, I tried deserializing into a List of Persons. That stopped the error message and I had the right number of "Person" records BUT they were all null. (I confirmed casing of names was identical.) I also don't really want to use a List collection when there is always only one element to the array from the target server and so binding to "Persons" makes more sense than "List".
What is the correct way to deserialize this JSON into Persons and still within the scope of my dynamic IRestResponse<T> response = client.Execute<T>(request) methodology?

As mentioned in the comments, your json holds an array of persons. Therefore the target structure to deserialize to should match that.
Either use:
var response = client.Execute<List<Person>>(request);
or if you prefer the Persons class, change it to
public class Persons : List<Person>
{
}

Related

newtonsoft deserialize group of objects

TL;DR
How do I convert json data that looks like this into a C# object using Newtonsoft.json and JsonConvert.DeserializeObject?
{"start":true,"result":{"label":"Setup Account","item":"name"}}
{"start":false,"result":{"label":"Change Account","item":"address"}}
{"start":false,"result":{"label":"Close Account","item":"account"}}
I am trying to deserialize some json exported from Splunk. The data does not look like an array, but rather a list of json objects between {}. Here are the first three objects of 600+ so you can see the format. The first one is actually the Splunk output. I shortened the "Search" in the next two.
{"preview":false,"result":{"label":"Internal Admin Nav","search":"<view isVisible=\"false\" >\n <label>Internal Admin Nav<\/label>\n <module name=\"Message\" layoutPanel=\"messaging\">\n <param name=\"filter\">*<\/param>\n <param name=\"clearOnJobDispatch\">False<\/param>\n <param name=\"maxSize\">1<\/param>\n <\/module>\n <module name=\"AccountBar\" layoutPanel=\"appHeader\">\n <param name=\"mode\">lite<\/param>\n <\/module>\n <module name=\"LiteBar\" layoutPanel=\"liteHeader\"><\/module>\n<\/view>"}}
{"preview":false,"result":{"label":"Setup Account","search":"AAAA"}}
{"preview":false,"result":{"label":"Contactless Dashboard","search":"BBBB"}}
If I try to create a class by pasting the first three lines into Visual Studio using Paste Special|Paste JSON as Classes, it complains that it is not Json data (Notepad++ seems to think it is though). If I just paste one of them {"preview":false,"result":{"label":"Contactless Dashboard","search":"BBBB"}} I get this object:
public class Rootobject
{
public bool preview { get; set; }
public Result result { get; set; }
}
public class Result
{
public string label { get; set; }
public string search { get; set; }
}
I have tied to deserialize in many ways.
Rootobject jsonObj = JsonConvert.DeserializeObject<Rootobject>(File.ReadAllText(fileName));
Error: Additional text encountered after finished reading JSON content:
List<Rootobject> jsonObj = JsonConvert.DeserializeObject<List<Rootobject>>(File.ReadAllText(fileName));
Error: Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ChecSourcetypes.Program+ObjClass]' 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 'preview', line 1, position 11.'
This is the most promising one and I tried to force it to deserialize by using a JsonObjectAttribute, but that just raised more problems.
I also added this class
public class RootRootobject
{
public List<Rootobject> objects { get; set; }
}
and then used this:
RootRootobject jsonObj = JsonConvert.DeserializeObject<RootRootobject>(File.ReadAllText(fileName));
I have messed with List<> and different objects without any success. I even converted the data to look like this:
[{"preview":false,"result":{"label":"Internal Admin Nav","search":"CCC"}},
{"preview":false,"result":{"label":"Setup Account","search":"AAAA"}},
{"preview":false,"result":{"label":"Contactless Dashboard","search":"BBBB"}}]
How do I read this json into an object? I would not want to change the Splunk output, but I could. I also would like to do it using JsonConvert.DeserializeObject. I recall doing this with Splunk data a few years ago using List<>, but do not remember how.
Thanks.
you have to fix your json to this (actually your last case)
[{"preview":false,"result":{"label":"Internal Admin Nav","search":"CCC"}},
{"preview":false,"result":{"label":"Setup Account","search":"AAAA"}},
{"preview":false,"result":{"label":"Contactless Dashboard","search":"BBBB"}}]
use your first classes
public class Rootobject
{
public bool preview { get; set; }
public Result result { get; set; }
}
and this code
List<RootRootobject> jsonObj = JsonConvert.DeserializeObject<List<RootRootobject>>(yourFixedJson);

Json Array cannot be deserialized

I would like to start by saying that I am not a developer and this is my very first time writing a code to this extend of complication (at least to me). Any help/guidance would be much appreciated.
The idea of this program is to retrieve the employee user ID (or signature) from an API URL once the name has been entered.
I have a JSON String
[{"signature":"JDOW","firstName":"Jane","fullName":"Dow, Jane","lastName":"Dow"}]
I am trying to deserialize it to a collection. But I am getting an error. Can somebody direct me to the right way to fix this?
namespace TimeSheet_Try11_Models
{
public class Employeename
{
[JsonProperty("Signature")]
public string Signature { get; set; }
[JsonProperty("FirstName")]
public string FirstName { get; set; }
[JsonProperty("FullName")]
public string FullName { get; set; }
[JsonProperty("LastName")]
public string LastName { get; set; }
}
}
I a trying to convert using the following code:
uri = StaticStrings.UrlIora + name;
var response = wc.DownloadString(uri);
Employeename status = JsonConvert.DeserializeObject<Employeename>(response);
The error I am getting is:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'TimeSheet_Try11_Models.Employeename' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
Deserialize the Json data for collection as:
var status = JsonConvert.DeserializeObject<List<Employeename>>(response);
or
List<Employeename> status = JsonConvert.DeserializeObject<List<Employeename>>(response);
Another thing is that, no need to use attribute [JsonProperty("anyProperty")] with your properties. Json can be deserialized without using it in attributes.
After getting the deserialzed data in status object, any value can be fetched from that object as:
string signature = status.Select(js => js.Signature).First();
Similarly other values can also be taken from the status.
Your JSON string has square brackets ([]) around it, which means it is a collection of items.
This is why the Deserialiser is erroring.
You need to either remove those brackets to give just one employee object in the input string, or tell DeserializeObject that it is a List you are deserialising.
var converted = JsonConvert.DeserializeObject<List<Employeename>>(response);
Working Fiddle here

Deserialize objects from array nested inside Json response

I'm trying to deserialize some objects nested inside a Json response using Newtonsoft.Json. I want to deserialize the following Jsons Term objects into a list. I have many Term objects in the Json response, so performance and compactness is important to me. I also would only like to define the Term class as I do not care about the other data for the time being.
I have a model defined for Term:
public class Term
{
public string Known { get; set; }
public string Word { get; set; }
}
My Json looks like this:
{
"myName":"Chris",
"mySpecies":"Cat",
"myTerms":
[
{
"Term":
{
"Known":"true",
"Word":"Meow"
}
},
{
"Term":
{
"Known":"false",
"Word":"Bark"
}
}
]
}
My C# deserializing code:
var response = await httpClient.GetAsync(uri);
string responseString = response.Content.ReadAsStringAsync().GetResults();
var searchTermList = JsonConvert.DeserializeObject<List<Term>>(responseString);
The problem/error I'm receiving is, not sure how I can get these terms from the json response:
{Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current
JSON object (e.g. {"name":"value"}) into type
'System.Collections.Generic.List`1[CoreProject.Models.Term]' 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<T>)
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.
Any suggestions would be greatly appreciated :)
You are getting that error because you are trying to deserialize the JSON into a List<T> for some T (specifically Term), but the root JSON container is not an array, it is an object -- an unordered set of key/value pairs surrounded by { and } -- that contains a fairly deeply embedded collection of objects corresponding to your Term.
Given that, you could use http://json2csharp.com/ or Paste JSON as Classes to auto-generate a complete data model corresponding to your JSON, then deserialize to that model and select out the interesting portions.
If, however, you don't want to define a complete data model, you can selectively deserialize only the relevant portions by loading your JSON into an intermediate JToken hierarchy and then using
SelectTokens():
var root = JToken.Parse(responseString);
var searchTermList = root.SelectTokens("myTerms[*].Term")
.Select(t => t.ToObject<Term>())
.ToList();
Notes:
The query string "myTerms[*].Term" contains the JSONPath wildcard operator [*]. This operator matches all array elements under the parent element "myTerms".
Json.NET supports JSONPath syntax as documented in Querying JSON with JSONPath.
If the JSON is more complex than is shown in your question, you can use the JSONPath recursive descent operator ... instead to find Term objects at any level in the JSON object hierarchy, e.g.:
var searchTermList = root.SelectTokens("..Term")
.Select(t => t.ToObject<Term>())
.ToList();
Once the relevant JSON objects have been selected you can use Jtoken.ToObject<Term>() to deserialize each one to your final c# model.
Sample fiddle.
Give this a try
public class Term
{
public string Known { get; set; }
public string Word { get; set; }
}
public class Response
{
public List<TermWrapper> MyTerms { get; set; }
}
public class TermWrapper
{
public Term Term { get; set; }
}
...
var response = await httpClient.GetAsync(uri);
string responseString = response.Content.ReadAsStringAsync().GetResults();
var searchTermList = JsonConvert
.DeserializeObject<Response>(responseString)
.MyTerms
.Select(x => x.Term);
You have to consider the full structure of the JSON. You have an object with 3 properties. The one you are interested in is an Array of Objects, but the objects are not terms, they are objects with a property called "Term". That property itself is of type Term. By creating the classes with similar structure you can then pull all the necessary data out of the structure.

How to convert JSON Response to a List in C#?

This might be a basic question but I am stuck while converting a JSON Response to a List.
I am getting the JSON Response as,
{"data":[{"ID":"1","Name":"ABC"},{"ID":"2","Name":"DEF"}]}
Have defined a Class,
class Details
{
public List<Company> data { get; set; }
}
class Company
{
public string ID { get; set; }
public string Name { get; set; }
}
Have tried this for converting,
List<Details> obj=List<Details>)JsonConvert.DeserializeObject
(responseString, typeof(List<Details>));
But this returns an error, saying
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Client.Details]' 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.
Kindly help!
You don't have a List<Detail> defined in your JSON. Your JSON defines one Detail record, which itself has a list of companies.
Just deserialize using Details as the type, not List<Details> (or, if possible, make the JSON wrap the single detail record into a one item array).
You need to Deserialize like this:
var Jsonobject = JsonConvert.DeserializeObject<Details>(json);
using classes generated by json2csharp.com:
var Jsonobject = JsonConvert.DeserializeObject<RootObject>(json);
and your classes should be :
public class Datum
{
public string ID { get; set; }
public string Name { get; set; }
}
public class RootObject
{
public List<Datum> data { get; set; }
}
you can always use json2csharp.com to generate right classes for the json.
You can use JavaScriptDeserializer class
string json = #"{""data"":[{""ID"":""1"",""Name"":""ABC""},{""ID"":""2"",""Name"":""DEF""}]}";
Details details = new JavaScriptSerializer().Deserialize<Details>(json);
EDIT: yes, there's nothing wrong with OP's approach, and Servy's answer is correct. You should deserialize not as the List of objects but as the type that contains that List

How to convert a Json string to a class that has a list in Json.Net with C# when the json has an array one level deeper

I have a C# Application in which I am using Json.Net from Nuget.
I get a json from my server which I need to convert into a C# object and with a few modifications I will send it back to the server as json.
Here's my model in C# (which I got after converting the server xsd)
public class Tags
{
public List<Tag> tagData { get; set; }
}
public class Tag
{
public string name {get; set;}
}
Here's my JSON string that is obtained from the server and an attempt at conversion to my model
//Json string obtained from server (hardcoded here for simplicity)
string json = "{tagData: {tags : [ { name : \"John\"}, { name : \"Sherlock\"}]}}";
//An attempt at conversion
var output = JsonConvert.DeserializeObject<Tags>(json);
This is the exception I get with the above code
An unhandled exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll
Additional information: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[jsonnetExample.Tag]' 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<T>) 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 'tagData.tags', line 1, position 17.
After understanding the above message I tried the following 2 things in the hope of fixing it.
A.I tried putting a JsonProperty to my first model.
[JsonProperty(PropertyName = "tags")]
This didn't throw the exception anymore but the output tagData was null.
B. I modified my model as follows
public class Tags
{
public WrapTag tagData { get; set; }
}
public class WrapTag
{
public List<Tag> tags { get; set; }
}
public class Tag
{
public string name {get; set;}
}
This didn't throw any exception and populated the objects as expected. But Now I lost the one to one mapping between xsd(classes from the server) to my client model classes. Is it possible to get this deserialization working without the creation of the WrapTag class?
I would be very glad if someone can point me in the right direction.
Thanks in advance.
Here's one option, using JObject.Parse:
string json = "{tagData: {tags : [ { name : \"John\"}, { name : \"Sherlock\"}]}}";
List<Tag> tagList = JObject.Parse(json)["tagData"]["tags"].ToObject<List<Tag>>();
// or:
// List<Tag> tagList = JObject.Parse(json).SelectToken("tagData.tags")
// .ToObject<List<Tag>>();
Tags tags = new Tags { tagData = tagList };

Categories