Deserializing JSON with Newtonsoft, using a specific class - c#

I know there are lots of questions on how to do this...
I have a pretty complex JSON returned from an API and I am trying to work my way through it. I simplified the JSON answer so it holds one of the immanent problems.
The simplified JSON answer
{"data":[{"type":"task","id":"10118"},{"type":"task","id":"10004"}]}
My class to be used for the deserialisation
namespace TestJsonDeserializeApp
{
class jsonTask
{
public List<Data> data { get; set; }
public class Data
{
public string id { get; set; }
public string type { get; set; }
}
}
}
How I want to do the deserialisation
List<jsonTask> test = JsonConvert.DeserializeObject<List<jsonTask>>(strJSON);
and finally the error message I am getting
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[TestJsonDeserializeApp.jsonTask]' 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 'data', line 1, position 8.
Can one of you tell me how I have to write the jsonTask class to fit the structure of the JSON input?

Copy your JSON. Open Visual studio. Create new C# class file. Now Select below menu option:
Edit > Paste Special > Paste JSON as classes
This will create a class as below
public class Rootobject
{
public Datum[] data { get; set; }
}
public class Datum
{
public string type { get; set; }
public string id { get; set; }
}
Now change RootObject to jsonTask and deserialise as below
jsonTask test = JsonConvert.DeserializeObject<jsonTask>(strJSON);

With your code you are casting the strJSON to List with a list. You need to remove the outer list since jsonTask alreadyhas the public List data { get; set; }
Try:
jsonTask test = JsonConvert.DeserializeObject(strJSON);

Related

Deserializing multiple Json objects from URL to List<T> in c#

I am trying to deserialize multiple Json objects from an API call like this: http://jservice.io/api/clues?category=2537&value=400
But when I run my code, I never get past the Json conversion and nothing is returned to the client when calling the GetQuestions() method.
I wanted to save the id, question, answer and value in a custom c# object so I made this class:
public class JsonQuestion
{
private DataContainer container;
public int id { get; set; }
public string answer { get; set; }
public string question { get; set; }
public int value { get; set; }
public JsonQuestion(string categoryId, int value)
{
using (var webClient = new System.Net.WebClient())
{
var json = webClient.DownloadString("http://jservice.io/api/clues?category=" + categoryId + "&value=" + value);
container = JsonConvert.DeserializeObject<DataContainer>(json);
}
}
public DataContainer GetQuestions()
{
return container;
}
}
Here I am receiving the categoryID and value to the constructor and then creating the URL based on those values to be deserialized. Ideally I want to return the container holding all the questions to a client.
I made a class that holds all the questions received:
public class DataContainer
{
public List<JsonQuestion> Questions { get; set; }
}
Which I use with the DeserializeObject call.
First of all you have wrong idea of how json will deserialize arrays. If you would look at exceptions that is throwing in your code you would get your first mistake:
Additional information: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Application.Program+DataContainer' 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.
What you are trying to do is deserialize array into object, witch is not possible. So you would need structure of json like this: {"Questions":[content of your json]}. To avoid this you have to change your deserialization to:
JsonConvert.DeserializeObject<List<JsonQuestion>>(json);
Second, JsonConvert will take simplest constructor provided, and will try to use it to create nested sturctures, witch you have multiple. So every time constructor has to be called, JsonConvert will use public JsonQuestion(string categoryId, int value) with fallowing values of null, and 400 (those value are taken form nested item, witch has parameter value set to 400 and no parameter categoryId). So you will fall into recuring loop, becase every time new json document will be downloaded. What you have to do is provide public default constructor of JsonQuestion.
Whole code would look like this:
public class JsonQuestion
{
private List<JsonQuestion> container;
public int id { get; set; }
public string answer { get; set; }
public string question { get; set; }
public int value { get; set; }
public JsonQuestion()
{
}
public JsonQuestion(string categoryId, int value)
{
using (var webClient = new System.Net.WebClient())
{
var json = webClient.DownloadString("http://jservice.io/api/clues?category=" + categoryId + "&value=" + value);
var container = JsonConvert.DeserializeObject<List<JsonQuestion>>(json);
}
}
public DataContainer GetQuestions()
{
return new DataContainer
{
Questions = container,
};
}
}
public class DataContainer
{
public List<JsonQuestion> Questions { get; set; }
}

Cannot deserialize the current JSON object (e.g. {"name":"value"})

Please Help me out i am new in xamarin.forms and C# i have try every solution which is given in stackoverflow but cannot avail to solve
using (var httpClient = new HttpClient())
{
var response = httpClient.GetAsync(Url).Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string contents = await responseContent.ReadAsStringAsync();
List<abcModel> tm = JsonConvert.DeserializeObject<List<abcModel>>(contents);
abcMaster = new ObservableCollection<SummaryModel>();
var c = tm[0].SSum.Count();
}
}
Model
public class abcModel
{
public List<SSum> SSum { get; set; }
}
public class SSum
{
public string Name{ get; set; }
}
My Json
{"a":[{"SSum":[{"Name":"Earth"}]}]}
Error:-
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[abcModel]' 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.
Because you obviously just want to deserialize a nested part of your json, do it like this:
var result = JsonConvert.DeserializeObject<Dictionary<string, List<abcModel>>>(json);
You're missing the a property in your JSON. You can deserialize into a class that has that property:
public class MyType
{
public List<abcModel> A { get; set; }
}
JsonConvert.DeserializeObject<MyType>(json);
Or skip that property all together (#stefankmitph's answer works well), here's another alternative:
JObject obj = JObject.Parse(json);
List<abcModel> model = obj["a"].ToObject<List<abcModel>>();
Just a note: normally C# classes are PascalCased.
If you already have the JSON string you should use a generator like json2csharp to create the response DTO. This will prevent mistakes in what is a collection versus single object.
public class SSum
{
public string Name { get; set; }
}
public class A
{
public List<SSum> SSum { get; set; }
}
public class RootObject
{
public List<A> A { get; set; }
}
Now you can deserialize the complete object:
tm = JsonConvert.DeserializeObject<RootObject>(contents);

Converting JSON to List

I am stuck in a step that I am sure should work. I have a method (in a separate class) that should return a List as its value after processing the JSON. I am going to paste the code skipping the JSON configuration stuff:
public static dynamic CustInformation(string Identifier)
{
//SKIPPED JSON CONFIG STUFF (IT'S WORKING CORRECTLY)
var result = "";
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
dynamic d;
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
}
return JsonConvert.DeserializeObject<List<Models.RootObject>>(result);
}
The model was generated using C# to Json converter:
public class Record
{
public string idIdentifier { get; set; }
public string KnowName1 { get; set; }
public string KnowAddress1 { get; set; }
public string KnowRelation1 { get; set; }
public string KnowPhone1 { get; set; }
public string KnowName2 { get; set; }
public string KnowAddress2 { get; set; }
//.....skipped other variables
}
public class RootObject
{
public List<Record> record { get; set; }
}
And I am calling the method like this:
var model = Classes.EndPoint.CustInformation(identifier);
Yet I am getting this error everytime:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Models.RootObject]' 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 'record', line 1, position 10.
EDIT: JSON
{
"record": [
{
Identifier": "DQRJO1Q0IQRS",
"KnowName1": "",
"KnowAddress1": "",
"KnowRelation1": "",
"KnowPhone1": "",
"KnowName2": "",
"KnowAddress2": "",
//.....MORE STYFF
}
]
}
Like I said in the comments, and like the error message clearly states, you're trying to deserialize into a list of root objects, but your JSON is only one root object, not an array.
Here's what your C# should be.
return JsonConvert.DeserializeObject<Models.RootObject>(result);

Deserializing json - wrong type

Here's how I try to deserialize my json:
new JavaScriptSerializer().Deserialize<Dictionary<int, MyModel>>(myData);
Here's the class:
public class MyModel
{
public Dictionary<int, ItemModel> Translation { get; set; }
public int Id { get; set; }
}
public class ItemModel
{
public string Name { get; set; }
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
}
And here's the json:
"[[],[],{"Translation":{"1":{"Name":"Bla1","ShortDescription":"bla1","LongDescription":"bla1"},"2":{"Name":"BlaUS1","ShortDescription":"BlaUS1","LongDescription":"BlaUS1"}},"Id":"12"},{"Translation":{"1":{"Name":"Bla22","ShortDescription":"bla22","LongDescription":"bla22"},"2":{"Name":"Bla2US2","ShortDescription":"Bla2US2","LongDescription":"Bla2US2"}},"Id":"13"}]"
and I get the error that the type is not supported for deserialization of an array.
Where is my error?
First of all your JSON looks a bit wrong to me. It is and array of 4 elements and 1st two elements are empty arrays but other two objects? I suspect your JSON should be something like that:
"[{"Translation":{"1":{"Name":"Bla1","ShortDescription":"bla1","LongDescription":"bla1"},"2":{"Name":"BlaUS1","ShortDescription":"BlaUS1","LongDescription":"BlaUS1"}},"Id":"12"},{"Translation":{"1":{"Name":"Bla22","ShortDescription":"bla22","LongDescription":"bla22"},"2":{"Name":"Bla2US2","ShortDescription":"Bla2US2","LongDescription":"Bla2US2"}},"Id":"13"}]"
Another issue is that you have Dictionary<int, ItemModel> but for serialization/deserialization you must have key of String or Object type.
Working example (providing that you changed from Dictionary<int, ItemModel> to Dictionary<object, ItemModel>):
string input = "[{\"Translation\":{\"1\":{\"Name\":\"Bla1\",\"ShortDescription\":\"bla1\",\"LongDescription\":\"bla1\"},\"2\":{\"Name\":\"BlaUS1\",\"ShortDescription\":\"BlaUS1\",\"LongDescription\":\"BlaUS1\"}},\"Id\":\"12\"},{\"Translation\":{\"1\":{\"Name\":\"Bla22\",\"ShortDescription\":\"bla22\",\"LongDescription\":\"bla22\"},\"2\":{\"Name\":\"Bla2US2\",\"ShortDescription\":\"Bla2US2\",\"LongDescription\":\"Bla2US2\"}},\"Id\":\"13\"}]";
List<MyModel> myModels = new JavaScriptSerializer().Deserialize<List<MyModel>>(input);
Your string suggests that what you have is a JSON array, eg:- [1,2,3]
but you are trying to deserialize it into a dictionary for which the json representation is akin to
{"1":"Hai","2":"Hello"}
obviously the library is throwing an error. May be why dont you use the following to deserialize the string.
new JavaScriptSerializer().Deserialize<List<MyModel>[]>(myData)
However, to use it you can't have empty arrays in the json, you have to fill them with default values for the properties.
To prove that the above works, try
"[{"Translation":{"1":{"Name":"Bla1","ShortDescription":"bla1","LongDescription":"bla1"},"2": {"Name":"BlaUS1","ShortDescription":"BlaUS1","LongDescription":"BlaUS1"}},"Id":"12"},{"Translation":{"1":{"Name":"Bla22","ShortDescription":"bla22","LongDescription":"bla22"},"2":{"Name":"Bla2US2","ShortDescription":"Bla2US2","LongDescription":"Bla2US2"}},"Id":"13"}]"
with
new JavaScriptSerializer().Deserialize<List<MyModel>>(myData)

Deserializing a heterogeneous JSON array using Json.NET

I have been searching for days, hours at a time trying to find an answer to my question. I have the following JSON string:
{
"id": "658#787.000a35000122",
"take": [{
"level": [0],
"status": [[3, [0]]]
}]
}
That is a sample of a variety of messages that I need to deserialize, but it is the one that is causing me heartache right now. The problematic portion for me is the "status" array. My class to accept the results of deserializing the string is:
[DataContract]
public class ReceivedMsg
{
public ReceivedMsg()
{
move = new List<MoveOperation>();
}
[DataMember]
public string id { get; set; }
[DataMember]
public List<MoveOperation> move { get; set; }
[DataContract]
public class Status
{
[DataMember]
public int destination { get; set; }
[DataMember]
public int[] source { get; set; }
}
[DataContract]
public class MoveOperation
{
public MoveOperation()
{
status = new List<Status>();
}
[DataMember]
public int[] level;
[DataMember]
public List<Status> status { get; set; }
}
}
The code to do the deserializing is:
ReceivedMsg m = new ReceivedMsg();
m = JsonConvert.DeserializeObject<ReceivedMsg>(strResp, new JsonSerializerSettings { TraceWriter = traceWriter });
Where strResp is the string containg the JSON data.
I initially tried using the JSON library that is a part of the .NET framework, but got stuck on the "status" portion. That's what prompted me to try Json.NET.
The error I am getting is:
An unhandled exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll
Additional information: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Roper.Roper+ReceivedMsg+Status' 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<T> 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 'move[0].status[0]', line 6, position 16.
Any help would be greatly appreciated. Of course I will be happy to furnish additional information as needed. I tried doing a custom converter, but I think my C# knowledge is not quite at that level yet. I have been trying to decipher the solutions offered in answer to similar questions, but concluded that I must be missing something.
My sincere thanks to the community for taking the time to read my lengthy question. Your generosity continues to amaze me!
If you're using Json.NET
(and if not you can install it using the NuGet package manager)
PM> Install-Package Newtonsoft.Json
This should then point you in the right direction :)
void Main()
{
string json = #"{
""id"": ""658#787.000a35000122"",
""take"": [{
""level"": [0],
""status"": [[3, [0]]]
}]
}";
RootObject root = JsonConvert.DeserializeObject<RootObject>(json);
}
public class Take
{
[JsonProperty("level")]
public int[] Level { get; set; }
[JsonProperty("status")]
public object[][] Status { get; set; }
}
public class RootObject
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("take")]
public Take[] Take { get; set; }
}

Categories