How to deserialize JSON to complex object in C# - 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; }
}

Related

Json.Net Deserialize dictionary without property name

I already looked at a lot of other questions with the same problem but never found a definitive solution that actually works for me. I tried using the JsonExtensionData Attribute, that doesn't work though since I can't convert my other data class to an object and it throws the Invalid extension data attribute on 'NAMESPACE'. Member 'Sols' type must implement IDictionary<string, JToken>. error.
My current data model class looks like this
public partial class Mars
{
public Dictionary<string, Sol> Sols { get; set; }
[JsonProperty("sol_keys")]
public List<long> SolKeys { get; set; }
}
public partial class Sol
{
[JsonProperty("AT")]
public At At { get; set; }
[JsonProperty("First_UTC")]
public DateTimeOffset FirstUtc { get; set; }
[JsonProperty("Last_UTC")]
public DateTimeOffset LastUtc { get; set; }
[JsonProperty("Season")]
public string Season { get; set; }
}
public partial class At
{
[JsonProperty("av")]
public double Av { get; set; }
[JsonProperty("ct")]
public long Ct { get; set; }
[JsonProperty("mn")]
public double Mn { get; set; }
[JsonProperty("mx")]
public double Mx { get; set; }
}
The json data looks like this
{
"651":
{
"AT":
{
"av": -61.957,
"ct": 302204,
"mn": -96.733,
"mx": -15.877
},
"First_UTC": "2020-09-25T02:42:14Z",
"Last_UTC": "2020-09-26T03:21:49Z",
"Season": "summer"
},
"652": {
"AT": {
"av": -65.002,
"ct": 278608,
"mn": -96.111,
"mx": -15.653
},
"First_UTC": "2020-09-26T03:21:50Z",
"Last_UTC": "2020-09-27T04:01:24Z",
"Season": "summer"
},
"sol_keys": [
"646",
"647",
"648",
"649",
"650",
"651",
"652"
]
}
I can't really modify the json data since I get it from an api.
I basically just want to select one of the numbers and then get the Sol data of that object.
Any help would be appreciated.
The JSON doesn't fit well with the C# type system. However, you can still use Json.Net to parse it. You just need to introduce some extra steps.
First step is to parse the JSON to a JObject:
var jObject = JsonConvert.DeserializeObject<JObject>(json);
Then you can extract the sol_keys:
var solKeys = jObject.GetValue("sol_keys").ToObject<long[]>();
Now it becomes a bit tricky. If you remove the sol_keys from the JSON (in this case the parsed JSON) it has the structure of a dictionary of Sol objects that you are able to parse:
jObject.Remove("sol_keys");
var mars = jObject.ToObject<Dictionary<long, Sol>>();
Now you have both solKeys and mars parsed from the JSON. Furthermore the solKeys and the keys in the dictionary share the same type (long).

Newtonsoft JSON Deserialize Issue [Error converting value to type]

Utilizing C# Newtownsoft JSON libraries... I have run into this issue.
To set the stage...
I have this JSON from a RESTful Web Service:
[
{
"CorporateArea": "Brampton",
"ServiceAddress": "321 Heart Lake Road",
"VendorName": "Enbridge Gas Distribution Inc",
"MeterNumber": "502105",
"RateClass": "NG-R6",
"Department": "22603",
"Account": "12008",
"VendorID": "0000001195",
"MeterLevelID": 2882,
"SiteAddressID": 468,
"MappingLocation": "Beckett Sproule",
"ElectricalBilling": "",
"EnergyLine": "",
"CorporateGroup": "Public Works"
}
]
I also have these C# classes:
public class AccountInfo
{
[JsonProperty("Account")]
public string Account { get; set; }
[JsonProperty("CorporateArea")]
public string CorporateArea { get; set; }
[JsonProperty("CorporateGroup")]
public string CorporateGroup { get; set; }
[JsonProperty("Department")]
public string Department { get; set; }
[JsonProperty("ElectricalBilling")]
public string ElectricalBilling { get; set; }
[JsonProperty("EnergyLine")]
public string EnergyLine { get; set; }
[JsonProperty("MappingLocation")]
public string MappingLocation { get; set; }
[JsonProperty("MeterLevelID")]
public string MeterLevelID { get; set; }
[JsonProperty("MeterNumber")]
public string MeterNumber { get; set; }
[JsonProperty("RateClass")]
public string RateClass { get; set; }
[JsonProperty("ServiceAddress")]
public string ServiceAddress { get; set; }
[JsonProperty("SiteAddressID")]
public string SiteAddressID { get; set; }
[JsonProperty("VendorID")]
public string VendorID { get; set; }
[JsonProperty("VendorName")]
public string VendorName { get; set; }
}
public class JSONArray {
public IList<AccountInfo> AccountsInfo { get; set; }
}
From these, I call this Newtownsoft Method:
JSONArray Accounts = JsonConvert.DeserializeObject<JSONArray> (responseBody,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
But everytime I do so, I get the exception Newtonsoft.Json.JsonSerializationException
with the error message:
Error converting value "[{"CorporateArea":"Brampton","ServiceAddress":"321 Heart Lake Road","VendorName":"Enbridge Gas Distribution Inc","MeterNumber":"502105","RateClass":"NG-R6","Department":"22603","Account":"12008","VendorID":"0000001195","MeterLevelID":2882,"SiteAddressID":468,"MappingLocation":"Beckett Sproule","ElectricalBilling":"","EnergyLine":"","CorporateGroup":"Public Works"}]" to type 'TestWebService_Consume.JSONArray'. Path '', line 1, position 421.
I've tried messing with the JSON string so it's not an array, and casting it into a simple AccountsInfo object, it returns the same error.
I must be doing something wrong, but it's been some time since I've worked with the Newtonsoft JSON libraries, so I'm at a loss of what could possible be the issue here.
The Deserialization output for the JSON is when trying with
JSONArray Accounts = JsonConvert.DeserializeObject<JSONArray>(json, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
is
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'JustSO.JSONArray' 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.
But if you try like this
List<AccountInfo> lc = JsonConvert.DeserializeObject<List<AccountInfo>>(json, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
or
List<AccountInfo> lc = JsonConvert.DeserializeObject<List<AccountInfo>>(json);
will give you the resultant json into Object.
Your JSOn is not an object, but an array of objects, so you don't need a class to wrap the array, you should deserialize directly to array:
var Accounts = JsonConvert.DeserializeObject<List<AccountInfo>>(responseBody,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
If you really want to have JSONArray object, you could create it and serialize to it's property. Just to mention: your AccountInfo property is private, you should change it to public to deserialize to it.
JSONArray Accounts = new JSONArray
{
AccountsInfo = JsonConvert.DeserializeObject<List<AccountInfo>>(responseBody,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
})
};
I use Newtonsoft.Json in generic read and write methods for Excel spreadsheets. Had this exception start throwing, and turned out to be a change made to the excel spreadsheet. In general column types, the first cell is used to set the data table type, generally with a header column this ends up being a string. The excel I was trying to load had a new row added at the top for zero indexing, so all columns were being set as system.double.
Just thought I'd throw that here, since it took a while to track down why this error started happening after years of working perfectly.

How to Deserialize JSON data? C#

Im getting a Json Data from an API and i have been trying to deserialize.
Json data:
{
   "items": [
      {
         "id": "1",
         "name": "samplename",
         "AddressList1": {
            "City": "Hyd",
            "State": "TN",
            "Country": "IN"
         },
         "Age": "10"
      },
      {
         "id": "2",
         "name": "samplename2",
         "AddressList1": {
            "City": "Hydd",
            "State": "TN",
            "Country": "IN"
         },
         "Age": "10"
      }
   ],
   "paging": {
      "cursors": {}
   }
}
Entities:
public class AddressList1
{
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
public class Item
{
public string id { get; set; }
public string name { get; set; }
public AddressList1 addressList1 { get; set; }
public string Age { get; set; }
}
public class Cursors
{
}
public class Paging
{
public Cursors cursors { get; set; }
}
public class Users
{
public List<Item> items { get; set; }
public Paging paging { get; set; }
}
C# code:
JsonConvert.DeserializeObject<List<Users>>(content);
Error Message:
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'System.Collections.Generic.List`1[Entities.Users]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly.
where am i doing wrong?
The following is a JSON-object; in your case a User
{ ... }
The following is a JSON-array; in your case an array of User
[ { ... }, { ... } ]
Thus if you want to deserialize the JSON you got into an array of Users this is not possible because you have no array in JSON.
Therefore the right code to deserialize is:
JsonConvert.DeserializeObject<Users>(content);
Furthermore your mapping is erroneous because in JSON there is a property AddressList1 and in the class it is called addressList1
Given your JSON, you would need a POCO object that contains a items member and a paging member.
JsonConvert.DeserializeObject<Users>(content);
should work.
Your Json string is good formatted and the entities are according to Json2Csharp good too.
but your problem is with the instruction JsonConvert.DeserializeObject<List<Users>>(content);
all that json that you have is only ONE User, and you are trying to get a list of them, there is the issue,
you can try instead with:
JsonConvert.DeserializeObject<Users>(content);
Try Below Code
JsonConvert.DeserializeObject<Users>(content);
Your entities(models) look just fine. If you are using, or were to use ASP.NET Web API 2, and your client is using the http verb post for example, this setup would work as Web API takes care of the object deserialization:
public HttpStatusCode Post(Item item)
{
Debug.Write(item.toString());
return HttpStatusCode.OK;
}
If you insist in deserializing manually then use the JavaScriptSerializer library which allows you to do things like:
Item item = new JavaScriptSerializer().Deserialize<Item>(content);
Notice that .Deserialize<T>() takes a generic which in your case it Item.
Hope that helps.

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);

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);

Categories