Convert Json to List<object> with .NET - c#

After days to try to convert Json to List of objects, I'm here.
I have a REST API that return the Json string:
{
GetItemsListResult:"[
{
"code":"VOL00056",
"clsID":223108653,
"type":2,
"status":1,
"free":0.0,
"total":671088640.0,
"perc":99,
"descr":"no mailing",
"dt":20160926,
"tm":112456,
"full":1
},
{
"code":"VOL00055",
"clsID":111760419,
"type":2,
"status":1,
"free":0.0,
"total":671088640.0,
"perc":99,
"descr":"Email",
"dt":20160817,
"tm":222411,
"full":1
}
]"
}
I know that this string comes from a DataTable:
String JSONresult = JsonConvert.SerializeObject(ds.Tables[0]);
I created two class: one that describe the object model and another that get the collection. But when trying to
VolumeCollection volumes = Newtonsoft.Json.JsonConvert.DeserializeObject<VolumeCollection>(listVolumes);
I obtain
Could not cast or convert from System.String to System.Collections.Generic.List`1[Volume].
What is wrong?
Volume Class:
public class Volume
{
public String code { get; set; }
public Int32 classId { get; set; }
public Byte volumeType { get; set; }
public Byte status { get; set; }
public float freeSpace { get; set; }
public float totalSpace { get; set; }
public Int16 fillPercentage { get; set; }
public String classDescription { get; set; }
public Int32 closeDate { get; set; }
public Int32 closeTime { get; set; }
public Boolean isFull { get; set; }
}
The json string received is:
"\"
[{\\"FreeSpace\\":0.0,\\"TotalSpace\\":671088640.0,\\"FillPercentage\\":99,\\"ClassDescription\\":\\"Email esterne\\",\\"CloseDate\\":20161001,\\"CloseTime\\":212512,\\"IsFull\\":true,\\"VolumeType\\":2,\\"ClassId\\":111760419,\\"Code\\":\\"VOL00057\\",\\"Status\\":1},
{\\"FreeSpace\\":0.0,\\"TotalSpace\\":671088640.0,\\"FillPercentage\\":99,\\"ClassDescription\\":\\"Corrispondenza no mailing\\",\\"CloseDate\\":20160926,\\"CloseTime\\":112456,\\"IsFull\\":true,\\"VolumeType\\":2,\\"ClassId\\":223108653,\\"Code\\":\\"VOL00056\\",\\"Status\\":1}
]\""
It seems to be a not valid json...

Given that your json is not valid and given that the following is:
{
"GetItemsListResult": [{
"code": "VOL00056",
"clsID": 223108653,
"type": 2,
"status": 1,
"free": 0.0,
"total": 671088640.0,
"perc": 99,
"descr": "no mailing",
"dt": 20160926,
"tm": 112456,
"full": 1
}, {
"code": "VOL00055",
"clsID": 111760419,
"type": 2,
"status": 1,
"free": 0.0,
"total": 671088640.0,
"perc": 99,
"descr": "Email",
"dt": 20160817,
"tm": 222411,
"full": 1
}]
}
using the following classes that I generated, this works:
public class GetItemsListResult
{
public string code { get; set; }
public int clsID { get; set; }
public int type { get; set; }
public int status { get; set; }
public double free { get; set; }
public double total { get; set; }
public int perc { get; set; }
public string descr { get; set; }
public int dt { get; set; }
public int tm { get; set; }
public int full { get; set; }
}
public class RootObject
{
public List<GetItemsListResult> GetItemsListResult { get; set; }
}
var res = JsonConvert.DeserializeObject<RootObject>(json);
N.B: this site generated the classes from the JSON: json2csharp

Your GetItemsListResult is a string, not an array. Notice the double quotes:
GetItemsListResult: "[
So, ideally you want to fix your json to be a real array.
If you don't have control over the json, then as a poor alternative you could recursively parse the strings to extract the array.

you have invalid json string:
1.1 valid json like this:
{
"GetItemsListResult":[
{"code":"VOL00056","clsID":223108653,"type":2,"status":1,"free":0.0,"total":671088640.0,"perc":99,"descr":"no mailing","dt":20160926,"tm":112456,"full":1},
{"code":"VOL00055","clsID":111760419,"type":2,"status":1,"free":0.0,"total":671088640.0,"perc":99,"descr":"Email","dt":20160817,"tm":222411,"full":1}
]
}
With http://json2csharp.com/ build data model
2.1 like this:
public class GetItemsListResult
{
public string code { get; set; }
public int clsID { get; set; }
public int type { get; set; }
public int status { get; set; }
public double free { get; set; }
public double total { get; set; }
public int perc { get; set; }
public string descr { get; set; }
public int dt { get; set; }
public int tm { get; set; }
public int full { get; set; }
}
public class RootObject
{
public List<GetItemsListResult> GetItemsListResult { get; set; }
}
with http://www.newtonsoft.com/json help parse you json
3.1 like this:
var jsonObj = JsonConvert.DeserializeObject<RootObject>(jsonString);

Related

How to deserialize specific json string to ASP.NET MVC model?

I have json string like this:
{
"data": [
{
"id": 1,
"name": "Bitcoin",
"symbol": "BTC",
...
"quote": {
"USD": {
"price": 9283.92,
"volume_24h": 7155680000,
"percent_change_1h": -0.152774,
"percent_change_24h": 0.518894,
"market_cap": 158055024432,
"last_updated": "2018-08-09T22:53:32.000Z"
},
"BTC": {
"price": 1,
"volume_24h": 772012,
"percent_change_1h": 0,
"percent_change_24h": 0,
"percent_change_7d": 0,
"market_cap": 17024600,
"last_updated": "2018-08-09T22:53:32.000Z"
}
}
},
// objects like previous from which i need the data
],
"status": {
"timestamp": "2018-06-02T22:51:28.209Z",
...
}
}
How do I deserialize it into models like this:
public class MyModel
{
public string Name { get; set; }
public string Symbol { get; set; }
public string Price { get; set; }
public double Percent_change_1h { get; set; }
public double Percent_change_24h { get; set; }
public long Market_cap { get; set; }
public DateTime Last_updated { get; set; }
}
The field names in the model are the same as the key names in json string.
I'm new to C# and I couldn't find any helpful information about my question, especially because of this specific json string structure.
I'll be glad if you direct me any good links about this.
The model seems to be something like this.
public class Model
{
public List<Datum> data { get; set; }
public Status status { get; set; }
}
public class Status
{
public DateTime timestamp { get; set; }
}
public class Datum
{
public int id { get; set; }
public string name { get; set; }
public string symbol { get; set; }
public Quote quote { get; set; }
}
public class Quote
{
public USD USD { get; set; }
public BTC BTC { get; set; }
}
public class BTC
{
public int price { get; set; }
public int volume_24h { get; set; }
public int percent_change_1h { get; set; }
public int percent_change_24h { get; set; }
public int percent_change_7d { get; set; }
public int market_cap { get; set; }
public DateTime last_updated { get; set; }
}
public class USD
{
public double price { get; set; }
public object volume_24h { get; set; }
public double percent_change_1h { get; set; }
public double percent_change_24h { get; set; }
public object market_cap { get; set; }
public DateTime last_updated { get; set; }
}
You can also try creating model on (http://json2csharp.com/) by copying your valid json string.
Please let me know if this helps
Bottom line: You can (manually), but that's probably not what you're looking for.
Reason: Your model doesn't match the JSON structure, hence "manual"
You can use readily available tools in either Visual Studio or VS Code to help you with creating the proper model (e.g. Paste JSON As Code)
Once you get the "proper" model/s ready, go over JSON documentation for (de)serializing.
I had to fix some syntax errors on your json, so fixed version is following:
{
"data": [
{
"id": 1,
"name": "Bitcoin",
"symbol": "BTC",
"quote": {
"USD": {
"price": 9283.92,
"volume_24h": 7155680000,
"percent_change_1h": -0.152774,
"percent_change_24h": 0.518894,
"market_cap": 158055024432,
"last_updated": "2018-08-09T22:53:32.000Z"
},
"BTC": {
"price": 1,
"volume_24h": 772012,
"percent_change_1h": 0,
"percent_change_24h": 0,
"percent_change_7d": 0,
"market_cap": 17024600,
"last_updated": "2018-08-09T22:53:32.000Z"
}
}
}
],
"status": {
"timestamp": "2018-06-02T22:51:28.209Z"
}
}
Here is C# model classes matching with previous json:
public class Rootobject
{
public Datum[] data { get; set; }
public Status status { get; set; }
}
public class Status
{
public DateTime timestamp { get; set; }
}
public class Datum
{
public int id { get; set; }
public string name { get; set; }
public string symbol { get; set; }
public Quote quote { get; set; }
}
public class Quote
{
public USD USD { get; set; }
public BTC BTC { get; set; }
}
public class USD
{
public float price { get; set; }
public long volume_24h { get; set; }
public float percent_change_1h { get; set; }
public float percent_change_24h { get; set; }
public long market_cap { get; set; }
public DateTime last_updated { get; set; }
}
public class BTC
{
public int price { get; set; }
public int volume_24h { get; set; }
public int percent_change_1h { get; set; }
public int percent_change_24h { get; set; }
public int percent_change_7d { get; set; }
public int market_cap { get; set; }
public DateTime last_updated { get; set; }
}
Here is code snippet which you can use when deserializing your json. This snippet uses Json.NET-library.
var obj = JsonConvert.DeserializeObject<Rootobject>(File.ReadAllText("object.json"));

Deserialize JSON array Object to c# class type conversion

I get JSON data from [HttpPost] in below format. I want to de-serialize to two C# Models.
data {{
"invoiceNumber": "55",
"invoiceDate": "2018-10-25T13:16:37.843Z",
"invoiceValue": 55,
"remarks": null,'
"items": [
{
"gRNNo": "0000000",
"itemCode": 1,
"itemDesc": "Lux",
"qty": "2",
},
{
"gRNNo": "0000000",
"itemCode": 2,
"itemDesc": "Rexona",
"qty": "1"
}
]
}}
I am able to get Header data but items array.
PurHeader purHeader = JsonConvert.DeserializeObject<PurHeader>(data.ToString()); //Working for Header
but failed in getting array data. I tried following.
List<PurDetail> purDetail = JsonConvert.DeserializeObject<List<PurDetail>>(data["items"].ToString());
var purDetail = JsonConvert.DeserializeObject<PurDetail[]>(data["items"].ToString());
My Classes - I use them in Code First. And data json comes from Angular 7 ReactiveForms
public class PurHeader
{
public string GRNNo { get; set; }
public string InvoiceNumber { get; set; }
public DateTime InvoiceDate { get; set; }
public decimal InvoiceValue { get; set; }
public string Remarks { get; set; }
public ICollection<PurDetail> PurDetail { get; set; }
}
public class PurDetail
{
public string GRNNo { get; set; }
public string ItemCode { get; set; }
public string ItemDesc { get; set; }
public decimal Qty { get; set; }
[ForeignKey("GRNNo")]
public PurHeader PurHeader { get; set; }
}
Your JSON is malformed, I hope that's just a typo in your question. However, you should be able to parse the whole set with these classes:
public class Rootobject
{
public string invoiceNumber { get; set; }
public DateTime invoiceDate { get; set; }
public int invoiceValue { get; set; }
public object remarks { get; set; }
public Item[] items { get; set; }
}
public class Item
{
public string gRNNo { get; set; }
public int itemCode { get; set; }
public string itemDesc { get; set; }
public string qty { get; set; }
}
Rootobject purHeader = JsonConvert.DeserializeObject<Rootobject>(data.ToString());
Also see my answer here on how to easily derive classes from XML (same applies to JSON): Parse This XML to object
Assuming your data doesn't have two {{ your code should work.
But you could do it without casting to string, just:
var purHeader = data.ToObject<PurHeader>();
var purDetails = data["items"].ToObject<PurDetail[]>();

Part of JSON returned by API is serialised by JSON.NET but not all

I imagine this is more of a problem with my code rather than a problem with JSON.NET, but I'm not sure where I'm going wrong.
I have the following class below which is being used to serialise the json data found at this link: https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22
To construct this class I used a JSON to C# generator found on google.
Also below are the methods I use to pull and serialise the JSON data into a WeatherData object.
private string GetJsonFromWeb(string resource, string city)
{
var request = new RestRequest(resource, Method.GET);
request.AddParameter("q", city);
request.AddParameter("APPID", "af5e6fd579e0ddb303afc1774487c77b");
var fullUrl = client.BuildUri(request);
Console.WriteLine("Full URL: " + fullUrl.AbsoluteUri);
var response = client.Execute(request);
string json = response.Content;
return json;
}
private WeatherData SerializeJsonToWeatherData(string json)
{
WeatherData weatherData = JsonConvert.DeserializeObject<WeatherData>(json);
return weatherData;
}
These methods work successfully, as the JSON data can be used later in the application to display information within the GUI. However the MainData part of the JSON data is set to null after the JSON is pulled from the API.
class WeatherData
{
public Coord Coord { get; set; }
public List<Weather> Weather { get; set; }
public string Base { get; set; }
public MainData MainData { get; set; }
public int Visibility { get; set; }
public Wind Wind { get; set; }
public Clouds Clouds { get; set; }
public int Dt { get; set; }
public Sys Sys { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public int Cod { get; set; }
}
public class Coord
{
public double Lon { get; set; }
public double Lat { get; set; }
}
public class Weather
{
public int Id { get; set; }
public string Main { get; set; }
public string Description { get; set; }
public string Icon { get; set; }
}
public class MainData
{
public double Temp { get; set; }
public int Pressure { get; set; }
public int Humidity { get; set; }
public double Temp_min { get; set; }
public double Temp_max { get; set; }
}
public class Wind
{
public double Speed { get; set; }
public int Deg { get; set; }
}
public class Clouds
{
public int All { get; set; }
}
public class Sys
{
public int Type { get; set; }
public int Id { get; set; }
public double Message { get; set; }
public string Country { get; set; }
public int Sunrise { get; set; }
public int Sunset { get; set; }
}
Sample JSON from above API
{
"coord": {
"lon": -0.13,
"lat": 51.51
},
"weather": [
{
"id": 300,
"main": "Drizzle",
"description": "light intensity drizzle",
"icon": "09d"
}
],
"base": "stations",
"main": {
"temp": 280.32,
"pressure": 1012,
"humidity": 81,
"temp_min": 279.15,
"temp_max": 281.15
},
"visibility": 10000,
"wind": {
"speed": 4.1,
"deg": 80
},
"clouds": {
"all": 90
},
"dt": 1485789600,
"sys": {
"type": 1,
"id": 5091,
"message": 0.0103,
"country": "GB",
"sunrise": 1485762037,
"sunset": 1485794875
},
"id": 2643743,
"name": "London",
"cod": 200
}
The JSON property is called main not mainData. JSON.Net can't find a property called mainData ans thus does not populate the MainData property of your POCOs

Deserializing a complex JSON object

I use JavaScript.Serializer.Deserializer to deserialize a complex JSON object, as below:
{
"name": "rule 1",
"enabled": true,
"conditions": [{
"type": "time",
"time": "17:23:10",
"days": "125"
}, {
"type": "sensor",
"uid": "10.2.0.1",
"setpoint1": 12,
"setpoint2": 18,
"criterion": 1
}, {
"type": "sensor",
"uid": "10.3.0.1",
"setpoint1": 12,
"setpoint2": 18,
"criterion": 2
}],
"actions": {
"period": 100,
"single": false,
"act": [{
"type": "on",
"uid": "10.1.0.1"
}, {
"type": "sms",
"message": "Hello World"
}]
}
}
And I want to convert it to some classes, like below:
public class Rule
{
public string name { get; set; }
public bool enabled { get; set; }
public List<Condition> conditions { get; set; }
public List<Action> actions { get; set; }
}
public class Condition
{
public string type { get; set; }
public string uid { get; set; }
public DateTime? time { get; set; }
public string days { get; set; }
public double setpoint1 { get; set; }
public double setpoint2 { get; set; }
public int criterion { get; set; }
}
public class Action
{
public int period { get; set; }
public bool single { get; set; }
public List<Act> act { get; set; }
}
public class Act
{
public string type { get; set; }
public string uid { get; set; }
public string message { get; set; }
}
The deserialization snippet:
json = new JavaScriptSerializer();
Rule rule = (json.Deserialize<Rule>(jsonStr));
If I simplify the Rule class and declare conditions and actions as simple strings, it works fine.
But if I use the classes like above, it throws an exception:
Cannot convert object of type 'System.String' to type 'System.Collections.Generic.List`1[IoTWebApplication.Condition]'
The structure you create does not fit to the JSON you posted.
It should look like
public class Rule
{
public string name { get; set; }
public bool enabled { get; set; }
public Condition[ ] conditions { get; set; }
public Actions actions { get; set; }
}
public class Actions
{
public int period { get; set; }
public bool single { get; set; }
public Act[ ] act { get; set; }
}
public class Act
{
public string type { get; set; }
public string uid { get; set; }
public string message { get; set; }
}
public class Condition
{
public string type { get; set; }
public string time { get; set; }
public string days { get; set; }
public string uid { get; set; }
public int setpoint1 { get; set; }
public int setpoint2 { get; set; }
public int criterion { get; set; }
}
It is (in most cases) very easy in VS to get the classes direct out of the JSON
Copy JSON to clipboard
In VS EDIT/Special Paste/Paste JSON as Classes (the code above was created by this)
The problem was that the inner (nested) json was quoted and therefore was processed as a string. So when I removed the quotes, it worked fine:
json = new JavaScriptSerializer();
Rule rule = (json.Deserialize<Rule>(jsonStr));

Deserializing an array of different object types

Using the Json.NET library, I'm having trouble deserializing some json returned as an array. The json is an array containing some paging information as an object and array of country objects. Here's a sample of the returned json:
[
{
"page": 1,
"pages": 6,
"per_page": "50",
"total": 262
},
[
{
"id": "ABW",
"iso2Code": "AW",
"name": "Aruba",
"region": {
"id": "LCN",
"value": "Latin America & Caribbean (all income levels)"
},
"adminregion": {
"id": "",
"value": ""
},
"incomeLevel": {
"id": "NOC",
"value": "High income: nonOECD"
},
"lendingType": {
"id": "LNX",
"value": "Not classified"
},
"capitalCity": "Oranjestad",
"longitude": "-70.0167",
"latitude": "12.5167"
}
]
]
I am attempting to deserialize to the following types:
class CountriesQueryResults
{
public PagingInfo PageInfo { get; set; }
public List<CountryInfo> Countries { get; set; }
}
class PagingInfo
{
public int Page { get; set; }
public int Pages { get; set; }
[JsonProperty("per_page")]
public int ResultsPerPage { get; set; }
public int Total { get; set; }
}
class CountryInfo
{
public string Id { get; set; }
public string Iso2Code { get; set; }
public string Name { get; set; }
public string Longitude { get; set; }
public string Latitude { get; set; }
public string CapitalCity { get; set; }
public CompactIdentifier Region { get; set; }
public CompactIdentifier AdminRegion { get; set; }
public CompactIdentifier IncomeLevel { get; set; }
public CompactIdentifier LendingType { get; set; }
}
class CompactIdentifier
{
public string Id { get; set; }
public string Value { get; set; }
}
I am calling DeserializeObject as so:
var data = JsonConvert.DeserializeObject<List<CountriesQueryResults>>(response);
I am getting the following error:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'CountriesQueryResults' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
I have been trying to get the answer from the documentation but I can't seem to figure it out. Any help would be appreciated.
Since your json is like this [ {....} , [{....}] ], You can only deserialize it to an object array(Where first item is an object and second, another array).
This simplest way I think to convert it to a c# object is:
var jArr = JArray.Parse(jsonstr);
var pageInfo = jArr[0].ToObject<PagingInfo>();
var countryInfos = jArr[1].ToObject<List<CountryInfo>>();
Class definitions would be:
public class PagingInfo
{
public int page { get; set; }
public int pages { get; set; }
[JsonProperty("per_page")]
public int ResultsPerPage { get; set; }
public int total { get; set; }
}
public class Region
{
public string id { get; set; }
public string value { get; set; }
}
public class AdminRegion
{
public string id { get; set; }
public string value { get; set; }
}
public class IncomeLevel
{
public string id { get; set; }
public string value { get; set; }
}
public class LendingType
{
public string id { get; set; }
public string value { get; set; }
}
public class CountryInfo
{
public string id { get; set; }
public string iso2Code { get; set; }
public string name { get; set; }
public Region region { get; set; }
public AdminRegion adminregion { get; set; }
public IncomeLevel incomeLevel { get; set; }
public LendingType lendingType { get; set; }
public string capitalCity { get; set; }
public string longitude { get; set; }
public string latitude { get; set; }
}
PS: You can change the property names' first char to Uppercase if you want. I used http://json2csharp.com/ to automatically generate those classes.

Categories

Resources