This is what the body looks like:
{
"_total": 3,
"users": [
{
"username": "person1",
"points": 3
},
{
"username": "person2",
"points": 2
},
{
"username": "person3",
"points": 1
}
]
}
The code:
public class UserData
{
public string username { get; set; }
public int points { get; set; }
}
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
var data = JsonConvert.DeserializeObject<List<UserData>>(body);
foreach (UserData userdata in data)
{
Debug.Log(userdata.username + ": " + userdata.points);
}
}
The Error:
JsonSerializationException: Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[UserData]'
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.
The class does not match the JSON structure, hence you are getting JsonSerializationException Exception.
Your model should look something like that:
public class RootClass
{
public int _total { get; set; }
public List<User> users { get; set; }
}
public class User
{
public string username { get; set; }
public int points { get; set; }
}
Than you can do this:
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
var data = JsonConvert.DeserializeObject<RootClass>(body);
foreach (User userdata in data.users)
{
Debug.Log(userdata.username + ": " + userdata.points);
}
}
you can parse a json string at first and after this to deserialize it to a list of UserData
var data = JObject.Parse(body)["users"].ToObject<List<UserData>>();
Related
here is my JSON response:
[
{
"Id": 25,
"CreateDate": "2020-09-26T12:25:27.917",
"Title": "Second TV Repair",
"categoryTitle": "Tv Repair",
"FirstName": "Sample FirsName",
"LastName": "Sample LastName"
} ]
here is my deserilizer class:
public class ServicemanHistory
{
public int Id { get; set; }
public DateTime CreateDate { get; set; }
public string Title { get; set; }
public string categoryTitle { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Here is my restsharp request method:
public static async Task<List<ServicemanHistory>> getServiceManHistory()
{
string url = "https://myapi.net";
string token = Settings.token;
var client = new RestClient(url);
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer " + token);
var response = await client.ExecuteAsync<List<ServicemanHistory>>(request);
Console.WriteLine("**** response is:" + response.Content);
if(response.IsSuccessful)
{
Console.WriteLine("SUCCESS!!!");
return response.Data;
} else
{
return null;
}
}
I get success printed in my console and I get the json returned from response.Content, but response.Data is always null. I did the same using NewtonSoft and that didn't fix it. And I tried using a wrapper for JSON array inside my deserializer class and didn't work either.
My attempt using NewtonSoft:
public static async Task<List<ServicemanHistory>> getServiceManHistory()
{
string url = "https://myapi.net";
string token = Settings.token;
var client = new RestClient(url);
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer " + token);
var response = await client.ExecuteAsync(request);
Console.WriteLine("**** response is:" + response.Content);
var result = JsonConvert.DeserializeObject<List<ServicemanHistory>>(response.Content);
if(response.IsSuccessful)
{
Console.WriteLine("SUCCESS!!!");
return result;
} else
{
return null;
}
}
I get the following error when trying to deserialize using NewtonSoft:
Newtonsoft.Json.JsonSerializationException
Message=Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List
o 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.
Good afternoon.
I need to deserialize the fields in JSON so that I can work with them as variables. I wrote a getter and setter for fields, loaded json from the url, but at the deserialization stage I get an error
"Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'GetDataFromUrl.JsonData' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly."
How do I correctly specify data for deserialization?
This type of JSON:
[
{
"Date": "2020-01-30",
"CountProblem": 10,
"Users": 8,
}
]
Code:
class JsonData
{
public DateTime Date { get; set; }
public int CountProblem { get; set; }
public int Users { get; set; }
}
class Report
{
static void Main(string[] args)
{
WebClient client = new WebClient();
var urlResponse = client.DownloadString("//my url");
JsonData jsondata = JsonConvert.DeserializeObject<JsonData>(urlResponse);
DateTime date = jsondata.Date;
int problemCount = jsondata.CountProblem;
int Users = jsondata.Users;
Console.WriteLine(Date + "," + CountProblem + "," + Users);
}
Your json string represents array not a single object, so try:
List<JsonData> jsondata = JsonConvert.DeserializeObject<List<JsonData>>(urlResponse);
I have this JSON string but are not sure how I will parse out the values that are inside:
has
has2
I do succeed to parse out the "id" correctly but are not sure how to access:
CORS
CORS2
CORS3
CORS4
I get the error:
'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.String[]' because the type requires a JSON array (e.g. [1,2,3])
I have pasted the JSON in the pastebin:
https://pastebin.com/iWgGV9VK
The code I have:
public void getInfo()
{
String JSONstring = "{ id: 'hello', name: 'Hello',has:{ CORS: false,CORS2: true},has2:{ CORS3: false,CORS4: true}}";
String id = ""; List<String> has = new List<String>(); List<String> has2 = new List<String>();
var deserializedTicker = JsonConvert.DeserializeObject<JsonInfo>(JSONstring);
id = deserializedTicker.id;
has = deserializedTicker.has.ToList();
has2 = deserializedTicker.has.ToList();
}
public class JsonInfo
{
public String id { get; set; }
public String[] has { get; set; }
public String[] has2 { get; set; }
}
I am trying with the dynamic approach using an object but gets an error here also:
''Newtonsoft.Json.Linq.JValue' does not contain a definition for 'id''
//responseBody holds the JSON string
dynamic stuff = JsonConvert.DeserializeObject(responseBody);
foreach (var info in stuff)
{
dynamic id = info.Value.id; //''Newtonsoft.Json.Linq.JValue' does not contain a definition for 'id''
dynamic has = info.Value.has;
dynamic has2 = info.Value.has2;
if (has != null && has2 != null)
{
dynamic cors = has.CORS;
if(cors != null)
{
MessageBox.Show(cors.ToString());
}
}
}
First off, let's correct your JSON:
{
"id": "hello",
"name": "Hello",
"has": {
"CORS": false,
"CORS2": true
},
"has2": {
"CORS3": false,
"CORS4": true
}
}
Now, the problem you are experiencing is because you are attempting to deserialize the value in "has" and "has2" as arrays. In the JSON, they are not arrays; they are objects. As such, you need to define new classes with the same properties so the JSON can be properly deserialized:
public class JsonInfo
{
public string id { get; set; }
public string name { get; set; }
public JsonHasInfo has { get; set; }
public JsonHas2Info has2 { get; set; }
}
public class JsonHasInfo
{
public bool CORS { get; set; }
public bool CORS2 { get; set; }
}
public class JsonHas2Info
{
public bool CORS3 { get; set; }
public bool CORS4 { get; set; }
}
Now you should be able to deserialize the (correct) JSON properly:
String JSONstring = "{ \"id\": \"hello\", \"name\": \"Hello\", \"has\": { \"CORS\": false, \"CORS2\": true }, \"has2\": { \"CORS3\": false, \"CORS4\": true } }\";"
var deserializedTicker = JsonConvert.DeserializeObject<JsonInfo>(JSONstring);
You json was incorrect, the key has contains a dict no list.
You need change your deserialize to dictionary or change your json.
Here you can see an example:
https://json-schema.org/understanding-json-schema/reference/array.html#array
In your JSON, has is an object, not an array. You should model your class to support an object containing the attributes CORS, CORS2, and so on, and so forth.
Edit: If you want to stick to has being an array, you should change your JSON to match what an array expects, which could be like: has: [ false, true ], and omit the CORS thing.
Is there a way to declare a class where for a specific variable I can receive either a List or a string?
I trying to deserialize a JSON and it can come in one of the formats below:
"MercadoriasPresencaCarga": {
"Mercadoria": 7693066,
"Descarga": "08/07/2017 13:35:39"
},
or
"MercadoriasPresencaCarga": {
"Mercadoria": [
"7693066"
],
"Descarga": [
"08/07/2017 13:35:39"
]
},
The class for this block is created like this:
public class MercadoriasPresencaCarga
{
public List<string> Mercadoria { get; set; }
public List<string> Descarga { get; set; }
}
The problem is that if this block of JSON come as the first format that I showed where it is not a array, it will cause an error on it deserialization.
How could I solve this problem?
Ideally the json should always come in the same format, but if that's not a possibility there are some workarounds.
Both json strings will deserialize successfully using the following class:
public class Model
{
// other properties here
// ....
[JsonIgnore]
public string Mercadoria => GetValue("Mercadoria");
[JsonIgnore]
public string Descarga => GetValue("Descarga");
public JObject MercadoriasPresencaCarga { get; set; }
private string GetValue(string path)
{
if (MercadoriasPresencaCarga == null)
{
return null;
}
string value = null;
JToken token = MercadoriasPresencaCarga.SelectToken(path);
if (token.Type == JTokenType.Array && token.HasValues)
{
value = token.First.Value<string>();
}
else
{
value = token.Value<string>();
}
return value;
}
}
Please note that:
MercadoriasPresencaCarga will be deserialized as JObject
Both Mercadoria and Descarga are non-serializable properties (marked with [JsonIgnore])
Testing the code - json string with string properties (no arrays):
string json1 = #"{
""MercadoriasPresencaCarga"": {
""Mercadoria"": 7693066,
""Descarga"": ""08/07/2017 13:35:39""
}
}";
Model model1 = JsonConvert.DeserializeObject<Model>(json1);
Console.WriteLine($"Descarga: {model1.Descarga}, Mercadoria: {model1.Mercadoria}");
Testing the code - json string with arrays:
string json2 = #"{
""MercadoriasPresencaCarga"": {
""Mercadoria"": [
""7693066""
],
""Descarga"": [
""08/07/2017 13:35:39""
]
}
}";
Model model2 = JsonConvert.DeserializeObject<Model>(json2);
Console.WriteLine($"Descarga: {model2.Descarga}, Mercadoria: {model2.Mercadoria}");
I'm trying to use JSON.NET to deserialize a response from a third-party web service. This is the full code of my (contrived) example showing what I'm trying to do:
namespace JsonNetTests
{
public enum Parameter
{
Alpha = 1,
Bravo = 2,
Charlie = 3,
Delta = 4
}
public class ResponseElement
{
public int Id { get; set; }
public string Name { get; set; }
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
public Parameter[] Parameters { get; set; }
}
public class ResponseBody
{
public string Locale { get; set; }
public string[] Errors { get; set; }
public ResponseElement[] ResponseElements { get; set; }
}
[TestFixture]
public class JsonNetTest
{
[Test]
public void TestEnumArray()
{
string jsonResponse = #"
{""ResponseBody"": {
""Locale"": ""en-US"",
""Errors"": [],
""ResponseElements"": [{
""Id"": 1,
""Name"": ""ABC"",
""Parameters"" : {
""Parameter"" : ""Alpha""
},
}, {
""Id"": 2,
""Name"": ""BCD"",
""Parameters"" : {
""Parameter"" : ""Bravo""
},
}
]
}}
";
JObject rootObject = JObject.Parse(jsonResponse);
JToken rootToken = rootObject.SelectToken("ResponseBody");
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MissingMemberHandling = MissingMemberHandling.Error;
ResponseBody body = JsonConvert.DeserializeObject<ResponseBody>(rootToken.ToString(), settings);
foreach (var element in body.ResponseElements)
{
Console.WriteLine(string.Format("{0}: {1}", element.Id, element.Name));
foreach (var parameter in element.Parameters)
{
Console.WriteLine(string.Format("\t{0}", parameter));
}
}
}
}
}
I get the following exception:
Newtonsoft.Json.JsonSerializationException : Cannot deserialize JSON object (i.e. {"name":"value"}) into type 'JsonNetTests.Parameter[]'.
The deserialized type should be a normal .NET type (i.e. not a primitive type like integer, not a collection type like an array or List) or a dictionary type (i.e. Dictionary).
To force JSON objects to deserialize add the JsonObjectAttribute to the type. Path 'ResponseElements[0].Parameters.Parameter', line 9, position 21.
I tried to use the ItemConverterType attribute to specify how the array should be deserialised:
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
But this does not help either. Can someone advise?
You're trying to stuff an object into an array. ResponseElement.Parameters is an array of enums where you're json code is using an object to describe each parameter.
Your json looks like this:
// some json
"Parameters" : {
"Parameter" : "Alpha"
},
// more json
But to translate it into an array of enums it should look like this:
// some json
"Parameters" : [ "Alpha", "Bravo" ],
// more json
If you can't change the json, you can change your model as so:
public enum ParameterEnum
{
Alpha = 1,
Bravo = 2
}
public ParameterContainer
{
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
public ParameterEnum Parameter {get;set;}
}
public class ResponseElement
{
public int Id { get; set; }
public string Name { get; set; }
public ParameterContainer[] Parameters { get; set; }
}
Effectively, you'll serialize the json into an array of ParameterContainers which will expose their values.