How to Deserialize a JSON Array from Web API in UPW C#? - c#

I want to connect to bitbay web api, get data JSON from there and save it to a file. My JSON looks like that:
{
"status": "Ok",
"items": [
{
"id": "737a2935-84c9-11ea-8cdc-0242ac11000e",
"t": "1587581134890",
"a": "0.00926098",
"r": "29999",
"ty": "Buy"
},
{
"id": "6c4474fa-84c9-11ea-8cdc-0242ac11000e",
"t": "1587581122794",
"a": "0.02475367",
"r": "29999",
"ty": "Buy"
}
]
}
I want to get t,a,r and ty from it. I've got code:
public class TradeModel
{
public decimal R { get; set; }
public decimal A { get; set; }
public string Ty { get; set; }
public DateTime T { get; set; }
}
public class TradeItemModel
{
public TradeModel Items { get; set; }
}
public class TradeProcessor
{
public static async Task<TradeModel> LoadTrades( int limit = 1 )
{
string url = "";
if (limit <= 300)
{
url = $"https://api.bitbay.net/rest/trading/transactions/BTC-PLN?limit={ limit }";
}
else
{
}
using (HttpResponseMessage response = await ApiHelper.ApiClient.GetAsync(url))
{
if (response.IsSuccessStatusCode)
{
TradeItemModel trade = await response.Content.ReadAsAsync<TradeItemModel>();
return trade.Items;
}
else
{
throw new Exception(response.ReasonPhrase);
}
}
}
}
After I run this code I gets an Exception:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'DemoLibrary.TradeModel' 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 'items', line 1, position 24.”

The Item in TradeItemModel class should be a collection TradeModel[] or List<TradeModel>, and you can also add Status to check it if is OK or KO:
public class TradeItemModel
{
public string Status { get; set; }
public List<TradeModel> Items { get; set; }
}
You must change also the method signature to:
public static async Task<List<TradeModel>> LoadTrades( int limit = 1 )
I hope this helps you out.

Related

Console App Failing to Deserialize the JSON

I'm receiving the following error when executing my code:
JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type
'AzureWinWorkloadList.AzureWinWorkloadList+Data[]' 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 'SkipToken', line 2, position
14.
This is a standalone console app not part of a MVC type project. Also, this had previously worked for me a few weeks back but when I went back to it, now I get that error.
Here is what my JSON looks like:
{
"SkipToken": null,
"Data": [
{
"name": "5678-PLACE-32",
"OSType": "Windows",
"CompName": "COMPUTER001",
"RGName": "RG1234",
"SubID": "AA1234567891011",
"SubName": "SUBNAME-Tool"
},
{
"name": "5678-PLACE-33",
"OSType": "Windows",
"CompName": "SERVER001",
"RGName": "RG1234",
"SubID": "AB1234567891011",
"SubName": "SUBNAME-Tool"
},
{
"name": "5678-PLACE-34",
"OSType": "Windows",
"CompName": "COMPUTER002",
"RGName": "RG1234",
"SubID": "AC1234567891011",
"SubName": "SUBNAME-Tool"
},
{
"name": "5678-PLACE-35",
"OSType": "Windows",
"CompName": "SERVER002",
"RGName": "RG1234",
"SubID": "AD1234567891011",
"SubName": "SUBNAME-Tool"
}
]
}
Here's my model Class:
public class Data
{
public string Name { get; set; }
public string OSType { get; set; }
public string CompName { get; set; }
public string RGName { get; set; }
public string SubID { get; set; }
public string SubName { get; set; }
}
Here is my Code:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace AzureWinWorkloadList
{
class AzureWinWorkloadList
{
static void Main(string[] args)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://samm-prod-azfun.azurewebsites.net/api/...");
var responseTask = client.GetAsync("");
responseTask.Wait();
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsAsync<Data[]>();
readTask.Wait();
var compnames = readTask.Result;
foreach (var CompName in compnames)
{
Console.WriteLine(CompName.CompName);
}
}
}
Console.ReadLine();
}
This is the line where the error occurs
readTask.Wait();
Any guidance on this would be appreciated!
Thanks in advance!
You need a wrapper class to deserialize the JSON data.
public class WrapperClass
{
public SkipTokenClass SkipToken { get; set; }
public IEnumerable<Data> Data { get; set; }
}
...
var readTask = result.Content.ReadAsAsync<WrapperClass>();
...
var wrapper = readTask.Result;
Use wrapper.Data to access the data.
Btw, aware that the property Name in Data class is different from the property name in the JSON data, consider use JsonPropertyAttribute.
[JsonProperty("name")]
public string Name { get; set; }

Issue in Deserializing JSON Response Data to List

i having issues getting the elements in data into a list.
I want to be able to get User_ID, Country, Continent and other elements to a list after which i will do a bulk insert to the database.
The Error i get
Error Message
An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in mscorlib.dll but was not handled in user code
Additional information: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Country_API.Response]' 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.
This is the JSon Data returned from the API
{
"Status": "200 Ok",
"Message": "Data retrieved",
"Response": {
"current_page": 1,
"data": [
{
"User-ID": "EAD001",
"Country": "Ghana",
"Continent": "Africa",
"Gender": "Male",
"Email": "ead1#yahoo.com",
"Religion": ""
},
{
"User-ID": "EAD002",
"Country": "Senegal",
"Continent": "Africa",
"Gender": "Female",
"Email": "ead2#yahoo.com",
"Religion": "Muslim"
}
]
}
}
I am trying to Deserilize but it throws the above error.. this is what i am trying
if (result.IsSuccessStatusCode)
{
string toJsonString = await result.Content.ReadAsStringAsync();
var deserialize = JsonConvert.DeserializeObject<List<Response>>(toJsonString);
}
Json Model
public class Data
{
public string User-ID { get; set; }
public string Country { get; set; }
public string Continent { get; set; }
public string Gender { get; set; }
public string Email { get; set; }
public string Religion { get; set; }
}
public class Response
{
public int current_page { get; set; }
public IList<Data> data { get; set; }
}
public class Application
{
public string Status { get; set; }
public string Message { get; set; }
public Response Response { get; set; }
}
How to i achieve this please?
You're trying to deserialize the List inside the object. You need to deserialize the entire object. Try this:
if (result.IsSuccessStatusCode)
{
string toJsonString = await result.Content.ReadAsStringAsync();
var deserialize = JsonConvert.DeserializeObject<Application>(toJsonString);
IList<Data> dataList = deserialize.Response.data;
}
Issue is here . You have used "List" instead of "Response". bcoz in JSON "Response" is object not a list
var deserialize = JsonConvert.DeserializeObject<List<Response>>(toJsonString);
use like this.
var deserialize = JsonConvert.DeserializeObject<Response>(toJsonString);

Json formatting error message when making GET HTTP Call

i'm trying to return a list of users from our software and format the names and email addresses of these users into a list so can compare this to other lists and determine what is more accurate. i'm making the request using the code below.
Question: How do I format my code to accept a json array as the error message states?
public void MakeCall()
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(Url);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync(_urlParameters).Result;
if (response.IsSuccessStatusCode)
{
var dataObjects = response.Content.ReadAsAsync<IEnumerable<WorkfrontDataObjects>>().Result;
foreach (var workfrontData in dataObjects)
{
Console.WriteLine("{0}", workfrontData.Email);
}
}
Console.ReadLine();
}
public class WorkfrontDataObjects
{
public string[] Email { get; set; }
public string[] Name { get; set; }
public WorkfrontDataObjects()
{
}
}
Error Message:
JsonSerializationException: Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type
'System.Collections.Generic.IEnumerable`1[ManageWorkfrontADUserDistros.WorkfrontDataObjects]'
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.
UPDATE, adding json:
{
"data": [
{
"ID": "000000000000000000000000000000",
"name": "name",
"objCode": "USER",
"emailAddr": "email"
},
{
"ID": "000000000000000000000000000000",
"name": "name",
"objCode": "USER",
"emailAddr": "email"
},
2500 of whats above with obviously real data
Given your JSON, your model needs to look like this:
public class RootObject
{
[JsonProperty("data")]
public List<Item> Data { get; set; }
}
public class Item
{
[JsonProperty("ID")]
public string ID { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("objCode")]
public string ObjCode { get; set; }
[JsonProperty("emailAddr")]
public string Email { get; set; }
}
You can rename the classes and properties to suit your needs without affecting the deserialization, as long as the names in the [JsonProperty] attributes match the JSON.
Then you should be able to receive the data like this:
if (response.IsSuccessStatusCode)
{
var rootObject = response.Content.ReadAsAsync<RootObject>().Result;
foreach (var item in rootObject.Data)
{
Console.WriteLine(item.Email);
}
}
Your string[] should be string in WorkfrontDataObjects and email should be emailAddr

How to deserialize JSON to complex object in C#

I'm trying to deserialize json result to wanted object. The result I'm getting is:
{
"base": "EUR",
"date": "2017-06-30",
"rates": {
"AUD": 1.4851,
"BGN": 1.9558,
"BRL": 3.76,
"CAD": 1.4785
}
}
I want this result to deserialize to my object:
public class ExchangeRates
{
public string Base { get; set; }
public DateTime Date { get; set; }
public IList<Rates> Rates { get; set; }
}
public class Rates
{
public string Name { get; set; }
public decimal Value { get; set; }
}
my deserialization looks like this:
using (var httpClient = new HttpClient())
{
var response = httpClient.GetAsync("http://api.fixer.io/latest").Result;
var result = response.Content.ReadAsStringAsync().Result;
var values = JsonConvert.DeserializeObject<ExchangeRates>(result);
}
When I run the program I get following exception:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ConsoleApp4.Rates]' 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 'rates.AUD', line 1, position 49.'
How can I deserialize JSON to my wanted object??
UPDATE 1
Or maybe I can just deserialize 'rates' list?
Take a look at your JSON, specifically rates:
"rates": {
"AUD": 1.4851,
"BGN": 1.9558,
"BRL": 3.76,
"CAD": 1.4785
}
This is very clearly a JSON object, as it has key-value pairs. However, looking at your code, you have defined the corresponding property (Rates) as an IList:
public IList<Rates> Rates { get; set; }
I understand your reasoning behind defining the Rates class. You think that by defining that class, NewtonSoft will deserialize rates the way you want it to. However, this is impossible because rates is not an array, and therefore deserializing it into any kind of IList is impossible.
The easiest and most clear cut solution is to use a dictionary:
public Dictionary<string, decimal> Rates { get; set; }
However, if you don't want to use a dictionary, you need to modify your JSON like so and your solution will work:
"rates":[
{
"Name":"AUD",
"Value":1.4851
},
{
"Name":"BGN",
"Value":1.9558
},
{
"Name":"BRL",
"Value":3.76
},
{
"Name":"CAD",
"Value":1.4785
}
]
By converting rates to an array, and making its contents objects instead of key-value pairs, NewtonSoft can deserialize rates as a list, and its contents as instances of the Rates class.
I agree with the other guys comments: you should use a Dictionary. To achieve the conversion to your final object structure you can use for example an intermediary class with an explicit cast operator.
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
public class Program
{
public void Main()
{
var result = #"{
""base"": ""EUR"",
""date"": ""2017-06-30"",
""rates"": {
""AUD"": 1.4851,
""BGN"": 1.9558,
""BRL"": 3.76,
""CAD"": 1.4785
}}";
var values = (ExchangeRates) JsonConvert.DeserializeObject<TempExchangeRates>(result);
Console.WriteLine(values.Base);
Console.WriteLine(values.Date);
foreach(var rate in values.Rates)
Console.WriteLine(rate.Name + ": " + rate.
}
}
public class TempExchangeRates
{
public string Base { get; set; }
public DateTime Date { get; set; }
public Dictionary<string,decimal> Rates { get; set; }
public static explicit operator ExchangeRates(TempExchangeRates tmpRates)
{
var xRate = new ExchangeRates();
xRate.Base = tmpRates.Base;
xRate.Date = tmpRates.Date;
xRate.Rates = new List<Rates>();
foreach(var de in tmpRates.Rates)
xRate.Rates.Add(new Rates{Name = de.Key, Value = de.Value});
return xRate;
}
}
public class ExchangeRates
{
public string Base { get; set; }
public DateTime Date { get; set; }
public IList<Rates> Rates { get; set; }
}
public class Rates
{
public string Name { get; set; }
public decimal Value { get; set; }
}

Deserializing an array of objects with Json.Net

The received data is like this:
Inside each item, there is an object, customer, I have an identical class for that. How can I convert them using Json.net?
I have tried the followings:
var data = JsonConvert.DeserializeObject<List<customer>>(val);
and adding another class:
public class customerJson
{
public Customer customer{ get; set; }
}
And trying to deserialize it:
var data = JsonConvert.DeserializeObject<List<customerJson>>(val);
With both of them I get an exception:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[customer]' 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 'rows', line 1, position 8.
Data:
{"rows":[{"id":"232333","name":"nam"},{"id":"3434444","name":"2ndName"}]}
If I read your json data structure correctly you would want this:
public class Root
{
public List<Customer> rows { get; set; }
}
and
var data = JsonConvert.DeserializeObject<Root>(val);
Tested code:
void Main()
{
var test = JsonConvert.DeserializeObject<Root>("{\"rows\":[{\"id\":\"232333\",\"name\":\"nam\"},{\"id\":\"3434444\",\"name\":\"2ndName\"}]}");
Console.WriteLine(test.rows[0].id); // prints 232333
}
public class Customer
{
public int id { get; set; }
}
public class Root
{
public List<Customer> rows { get; set; }
}
Just in case anyone is still having issues. This worked out for me:
If the Json looks something like this:
"result": [
{
"firstname": "John",
"lastname": "Doe",
},
{
"firstname": "Max",
"lastname": "Mustermann",
}
]
ResultList.cs
public class ResultList {
[JsonProperty("result")]
public List<ResultObj> ResultObj { get; set }
}
ResultObj.cs
public class ResultObj {
[JsonProperty("firstname")]
public string FirstName { get; set; }
[JsonProperty("lastname")]
public string LastName{ get; set; }
}
And finally:
using Newtonsoft.Json;
var resultList = JsonConvert.DeserializeObject<ResultList>(jsonString);

Categories