I am trying to use RiotGames Api. I have JSON data and I need to deserialize this JSON to c# classes but I get an error:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[WFALeagueOfLegendsAPI.Heroes]' 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 'datas.Aatrox', line 1, position 85.'
My Classes:
public class JsonRoot
{
public string type { get; set; }
public string format { get; set; }
public string version { get; set; }
public List<Heroes> datas { get; set; }
}
public class Heroes
{
public HeroesData Name { get; set; }
}
public class HeroesData
{
public string version { get; set; }
public string id { get; set; }
public string key { get; set; }
public string name { get; set; }
public string title { get; set; }
public HeroImage image { get; set; }
}
public class HeroImage
{
public string full { get; set; }
public string sprite { get; set; }
public string group { get; set; }
public override string ToString()
{
return full;
}
}
C# Code:
var json = new WebClient().DownloadString("http://ddragon.leagueoflegends.com/cdn/6.24.1/data/en_US/champion.json");
json = json.Replace("data", "datas");
JsonRoot jr = JsonConvert.DeserializeObject<JsonRoot>(json); // this line has the error
You are getting this error because you are using a List<Heroes> for the data, but that property is not an array in the JSON. You need to use a Dictionary<string, HeroesData> instead. The heroes' names will be the keys of the dictionary. Also, if you want to use a different name for a particular property in your class than what is in the JSON, you can use a [JsonProperty] attribute, as shown below. It's not really a good idea to use string.Replace to try to change the JSON to suit your classes, because you could end up replacing things you did not intend.
public class JsonRoot
{
public string type { get; set; }
public string format { get; set; }
public string version { get; set; }
[JsonProperty("data")]
public Dictionary<string, HeroesData> heroes { get; set; }
}
Fiddle: https://dotnetfiddle.net/kuKSrk
Related
I'm using the API of www.textlocal.in, which returns a JSON formatted object.
JSON
{
"warnings":[
{
"message":"Number is in DND",
"numbers":"917000000000"
}
],
"balance":900,
"batch_id":311110011,
"cost":1,
"num_messages":1,
"message":{
"num_parts":1,
"sender":"TXTLCL",
"content":"Test1"
},
"receipt_url":"",
"custom":"",
"inDND":[
"917000000000"
],
"messages":[
{
"id":"1350123781",
"recipient":918819437284
}
],
"status":"success"
}
My code with which I'm trying to parse the JSON:
private void button1_Click(object sender, EventArgs e)
{
var a = JsonConvert.DeserializeObject<List<jsonToObj[]>>(richTextBox1.Text);
}
public class jsonToObj
{
public warnings[] warnings { get; set; }
public int balance { get; set; }
public int batch_id { get; set; }
public int cost { get; set; }
public int num_messages { get; set; }
public message message { get; set; }
public string receipt_url { get; set; }
public string custom { get; set; }
public messages[] messages { get; set; }
public string status { get; set; }
}
public class warnings
{
public string message { get; set; }
public string numbers { get; set; }
}
public class messages
{
public string id { get; set; }
public int recipient { get; set; }
}
public class message
{
public int num_part { get; set; }
public string sender { get; set; }
public string content { get; set; }
}
I'm getting an exception with the following message:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the
current JSON object (e.g. {"name":"value"}) into type
'System.Collections.Generic.List`1[WindowsFormsApp1.Form2+jsonToObj[]]'
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 'warnings', line 1, position
12.'
First of all you have to figure out what your API returns.
Right now you're trying to parse a List of jsonToObj Arrays (List<jsonToObj[]>). You have to decide whether to use a jsonToObj[] or List<jsonToObj> or a simple jsonToObj which your API provides now:
var a = JsonConvert.DeserializeObject<jsonToObj>(richTextBox1.Text);
But this then throws:
JSON integer 918819437284 is too large or small for an Int32. Path 'messages[0].recipient', line 25, position 33."
So make sure you use a Long for that.
public class messages
{
public string id { get; set; }
public long recipient { get; set; }
}
Furthermore you can add inDND to your jsonToObj class if you need the info:
public class jsonToObj
{
...
public string[] inDND { get; set; }
...
}
Based on string you class structure should be like this :
public class Warning
{
public string message { get; set; }
public string numbers { get; set; }
}
public class Message
{
public int num_parts { get; set; }
public string sender { get; set; }
public string content { get; set; }
}
public class Message2
{
public string id { get; set; }
public long recipient { get; set; }
}
public class RootObject
{
public List<Warning> warnings { get; set; }
public int balance { get; set; }
public int batch_id { get; set; }
public int cost { get; set; }
public int num_messages { get; set; }
public Message message { get; set; }
public string receipt_url { get; set; }
public string custom { get; set; }
public List<string> inDND { get; set; }
public List<Message2> messages { get; set; }
public string status { get; set; }
}
It looks like your class structure is not proper, Make use of visual studio and generate C# class from json string and then using that generated class try to deserialize class.
Read : Visual Studio Generate Class From JSON or XML
I simulated your problem and made the following changes that worked:
Change the method that deserializes to this:
var a = JsonConvert.DeserializeObject<jsonToObj>(richTextBox1.Text);
The result of the JSON you receive is not a List, so it will not work to deserialize to List<>.
The recipient property of the messages class receives values larger than an integer, so it must be transformed into a long like this:
public long recipient { get; set; }
These changes solve your problem.
Looks like this is a very old post, still thought of answering.
First of all, your Json data is singular which means, either
var a = JsonConvert.DeserializeObject<List<jsonToObj[]>>(richTextBox1.Text);
or
var a = JsonConvert.DeserializeObject<List<jsonToObj>>(richTextBox1.Text);
may not work for you.
You can either try:
var a = JsonConvert.DeserializeObject<jsonToObj>(richTextBox1.Text);
or
enclose the data with [ and ], which would do the trick.
make sure your parsing single object vs list of objects.
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
// Deserialize the response to get an array of CUSTOM Cases
var reportsList = jsSerializer.Deserialize<SfdcObjects.SfdcCollection<SfdcObjects.Assets>>(HttpUtility.UrlDecode(response));
throws an exception:
Error: System.InvalidOperationException: Type 'SalesforceDataQueryComponent.Utils.SfdcObjects+SfdcCollection`1[
[SalesforceDataQueryComponent.Utils.SfdcObjects+Assets, SalesforceDataQueryComponent, Version=1.2.0.0, Culture=neutral]]'
is not supported for deserialization of an array.
I can not figure it out the issue:
Objects:
namespace SalesforceDataQueryComponent.Utils
{
class SfdcObjects
{
// Used for Authentication
public class TokenResponse
{
public string id { get; set; }
public string issued_at { get; set; }
public string refresh_token { get; set; }
public string instance_url { get; set; }
public string signature { get; set; }
public string access_token { get; set; }
}
// All classes shown next are used to parse the HttpGet Response
public class SfdcCollection<T>
{
public bool Done { get; set; }
public int Size { get; set; }
public string NextRecordsUrl { get; set; }
public List<T> Records { get; set; }
}
public class SfdcAttributes
{
public string Type { get; set; }
public string Url { get; set; }
}
public class Accounts : Account
{
public SfdcAttributes Attributes { get; set; }
}
public class Assets : Asset
{
public SfdcAttributes Attributes { get; set; }
}
public class CustomAssets : Assets
{
public string StringInstallDate { get; set; }
}
public class Users : User
{
public SfdcAttributes Attributes { get; set; }
}
public class CustomCase : Case
{
public string StringCreatedDate { get; set; }
}
public class CustomCases : CustomCase
{
public SfdcAttributes Attributes { get; set; }
}
}
}
You do not include your response JSON in your question, however from the error message, your problem must be that the root JSON container in your response is an array. A JSON array, according to the JSON standard, looks like this:
[value1, value2, ..., valueN]
JSON serializers map types that implement ICollection or IEnumerable from and to JSON arrays.
Your root object SfdcCollection<T>, however, is NOT a collection or enumerable, despite its name. Instead it's a non-enumerable generic POCO:
public class SfdcCollection<T> // No IEnumerable<T>
{
public bool Done { get; set; }
public int Size { get; set; }
public string NextRecordsUrl { get; set; }
public List<T> Records { get; set; }
}
Thus a serializer will map this to a JSON object (which is a set of key/value pairs and looks like {"name1" : value1, "name2" : value2, ..., "nameN" : valueN }) instead of an array.
You need to update your data model to the JSON you are actually receiving. Try uploading your JSON to http://json2csharp.com/, it will automatically generate classes for you.
If you must use the classes in your question, you could ask another question about how to map the JSON you are actually receiving onto your required classes, using your desired serializer (e.g. Json.NET, DataContractJsonSerializer, JavaScriptSerializer, or etc.)
I want to parse a piece of JSON with Newtonsoft Json.NET
JSON:
[{
"type": "switchStatus",
"Data" :[
{
"ID" : "1",
"value" : "2.5"
},
{
"ID" : "2",
"value" : "4.2"
}
],
"Datetime": "2014-12-01",
"customerID": "50"
}]
Classes:
public class Account
{
[JsonProperty("type")]
public string Type { get; set; }
public List<Data> Data { get; set; }
[JsonProperty("Datetime")]
public string DateTime { get; set; }
[JsonProperty("customerID")]
public string CustomerId { get; set; }
}//Account
public class Data
{
[JsonProperty("ID")]
public string Id { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
}
Parsing:
Account account = JsonConvert.DeserializeObject<Account>(message);
Error :
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'JSonParser.Account' 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.
Your problem is that your JSON doesn't match your declared class. Specifically, your Data property isn't a List<string>, its a complex object.
Your class should look like this:
public class Data
{
[JsonProperty("ID")]
public int Id { get; set; }
[JsonProperty("value")]
public double Value { get; set; }
}
public class Account
{
[JsonProperty("type")]
public string Type { get; set; }
public List<Data> Data { get; set; }
[JsonProperty("Datetime")]
public string DateTime { get; set; }
[JsonProperty("customerID")]
public int CustomerId { get; set; }
}
Edit:
As you've edited your JSON, it's clear now that you need a List<Account>, and not a single one. When you deserialize, you'll need:
List<Account> accounts = JsonConvert.DeserializeObject<List<Account>>(message);
You cannot Deserialize the data Data attribute like that. Since the list isnt a string to start with.
Try:
public class Data
{
public int ID { get; set; }
public float value { get; set; }
}//Data
public class Account
{
public string type { get; set; }
public List<Data> Data { get; set; }
public string Datetime { get; set; }
public string customerID { get; set; }
}//Account
I'm attempting to switch from VB.NET to C#; however I'm having some issues with JSON. I'm attempting to deserialize a JSON array. However, I get this error:
Cannot deserialize the current JSON array
Here's the class I'm deserializing into:
public class ReturnObject
{
public int id { get; set; }
public string name { get; set; }
public string url { get; set; }
public bool thumbnailFinal { get; set; }
public string thumbnailUrl { get; set; }
public object bcOverlayUrl { get; set; }
public object personalServerOverlayUrl { get; set; }
}
Deserialize code:
Debug.WriteLine(JsonConvert.DeserializeObject<ReturnObject>(richTextBox1.Text));
Here's the web URL to the JSON I'm attempting to retrieve.
http://www.roblox.com/place-thumbnails?params=[{placeId:1818}]
You're trying to deserialize a JSON array into just a single object, which can't be done.
Change your deserialization code to this:
var deserialized = JsonConvert.DeserializeObject<ReturnObject[]>(richTextBox1.Text)
To see the results:
foreach(var obj in deserialized)
{
Debug.WriteLine(obj.id);
}
Trying to read json via an API but getting the following error: I've tried a few things but always seem to get this error..
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Shared.Review]' 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 'status', line 1, position 10.
Model:
public class Reviewer
{
public string first_name { get; set; }
public string last_name { get; set; }
public string verified_buyer { get; set; }
public string profile_picture { get; set; }
}
public class Review
{
public string product_review_id { get; set; }
public string name { get; set; }
public string review { get; set; }
public string rating { get; set; }
public string date_created { get; set; }
public string timeago { get; set; }
public string date_formatted { get; set; }
public string product { get; set; }
public List<object> ratings { get; set; }
public Reviewer reviewer { get; set; }
}
public class RootObject
{
public string status { get; set; }
public List<Review> reviews { get; set; }
public int count { get; set; }
public string rating { get; set; }
public string per_page { get; set; }
public string current_page { get; set; }
public int total_pages { get; set; }
}
c# Code:
var reviews = JsonConvert.DeserializeObject<List<Review>>(json);
StringBuilder reviewsString = new StringBuilder();
foreach (var review in reviews)
{
reviewsString.AppendFormat("<div class=\"review\">");
reviewsString.AppendFormat("<p class=\"review-title\">Snugg Case</p>");
reviewsString.AppendFormat("<div class=\"rating\">");
reviewsString.AppendFormat("<span class=\"star\"></span>");
reviewsString.AppendFormat("<span class=\"star\"></span>");
reviewsString.AppendFormat("<span class=\"star\"></span>");
reviewsString.AppendFormat("<span class=\"star\"></span>");
reviewsString.AppendFormat("<span class=\"halfStar\"></span>");
reviewsString.AppendFormat("</div>");
reviewsString.AppendFormat("<p class=\"review-details\">{0}</p>",
review.review);
reviewsString.AppendFormat("<p class=\"review-name\">{0}</p>",
review.name);
reviewsString.AppendFormat("<p class=\"review-date\">{0}</p>",
review.date_formatted);
reviewsString.AppendFormat("</div> ");
topSectionReviews.Text += reviewsString;
}
Example Json:
http://pastebin.com/HNhNDMhr
Any questions just ask
Thanks in advance,
Michael
You're trying to deserialize into a collection:
var reviews = JsonConvert.DeserializeObject<List<Review>>(json);
However your Json isn't a collection at the top level since that would mean the json string would start and end with []. Instead it is surrounded by {} which indicates a single object.
It looks like you want to deserialize as a single RootObject instead:
var reviews = JsonConvert.DeserializeObject<RootObject>(json);
since this has a field List<Review> reviews and string status.
Not that you are not following naming conventions. Use proper naming and the [JsonProperty("something")] attribute to correctly parse the json.