I am using RestSharp to consume a restful webservice. I am using the built in Json Deserializer to deserialize the response.
This is the response.
[{"id":"1","latitude":"18.0155848","longitude":"-77.4988293","rating":"1","streetid":"1","username":"joel","verified":"1"},{"id":"2","latitude":"18.0155892","longitude":"-77.498774","rating":"1","streetid":"2","username":"joel","verified":"0"},{"id":"3","latitude":"18.0227736","longitude":"-77.4980039","rating":"1","streetid":"3","username":"joel","verified":"0"}]
These are the models its being mapped to.
List<Pothole> list = new List<Pothole>();
public class Pothole
{
//getters and setters for the attributes of Pothole Model
public long Id { get; set;}
public double Latitude { get; set; }
public double Longitude { get; set; }
public double Rating{ get;set;}
public long StreetId { get; set; }
public string Username { get; set; }
public bool Verified { get; set; }
}
However when I make the call the data is not being deserialized.I am wondering if there is a problem with the json response to the class mapping. I am mapping the response to a list of potholes due to an array of pothole objects being returned. I check the HTTP status code and the content of the response so the data is being returned, its just the deserializing causing a problem.
Try this:
public class Pothole
{
public string id { get; set; }
public string latitude { get; set; }
public string longitude { get; set; }
public string rating { get; set; }
public string streetid { get; set; }
public string username { get; set; }
public string verified { get; set; }
}
C# is case sensitive and so the reflection that takes place in populating the C# object will look for properties with names EXACTLY like those in the JSON string.
Also, if you're using Visual Studio 2012 SP 1 you can actually paste JSON text as a C# class. Pretty handy.
Or you can also use : Json2Csharp
generate c# classes from json
Late to the party but I thought I'd throw in my $0.02. I am using an unmodified version of RestSharp.Portable 1.6.2 Xamarin PCL
I have json as follows:
{"blah":{"iPAddress":"10.1.1.x","cPU":"1 vCPU","dNSName":"blah.blah.com"}}
with the class below, the deserialzation does not work for CPU, works for DSName, and IPAddress though.
public class Blah
{
public string CPU { get; set; }
public string DNSName { get; set; }
public string IPAddress { get; set; }
}
However if I change CPU to cPU it works fine.
public class Blah
{
public string cPU { get; set; }
public string DNSName { get; set; }
public string IPAddress { get; set; }
}
So, feels like a bug, just wanted to contribute.
Related
My goal is to build an API that can load currency data from https://openexchangerates.org/ api into our SQLite database. I am able to get the JSON object formatted like this:
When i run the code below, it returns an errors. I am not sure how to resolve this. Just need to convert this JSON into a C# class without error.
Here's the custom C# object to mapped to JSON obj:
public class ExchangeRate
{
public string Disclaimer { get; set; }
public string License { get; set; }
public string Timestamp { get; set; }
public string Base { get; set; }
public string Rates { get; set; }
}
Here is the api call where its returning the error:
public static async Task<List> GetLatest(string url)
{
var client = new HttpClient();
string results = await client.GetStringAsync(url);
List<ExchangeRate> ratesList = JsonConvert.DeserializeObject<List<ExchangeRate>>(results);
return ratesList;
}
The example JSON is not a list, it's a single object, this is specified in the exception message
...because the type requires a JSON array
, otherwise it would have [ ] around it indicating an array (can be deserialized to list). Also, your model is flawed as Rates is not a string, but an object, and Timestamp is not a string but a long for the datetime as ticks. Change your model like so:
public class ExchangeRate
{
//decorate your properties since the json string uses lowercase
[JsonProperty("disclaimer")]
public string Disclaimer { get; set; }
[JsonProperty("license")]
public string License { get; set; }
[JsonProperty("timestamp")]
public long Timestamp { get; set; }
[JsonProperty("base")]
public string Base { get; set; }
[JsonProperty("rates")]
public Rates Rates { get; set; }
}
public class Rates
{
//create the properties for the Rates class
}
OR make the rates property a Dictionary<string, decimal>, NOTE: this could fail if any key is duplicated.
public class ExchangeRate
{
//decorate your properties since the json string uses lowercase
[JsonProperty("disclaimer")]
public string Disclaimer { get; set; }
[JsonProperty("license")]
public string License { get; set; }
[JsonProperty("timestamp")]
public long Timestamp { get; set; }
[JsonProperty("base")]
public string Base { get; set; }
[JsonProperty("rates")]
public Dictionary<string, decimal> Rates { get; set; }
}
Change your code to this:
ExchangeRate rate = JsonConvert.DeserializeObject<ExchangeRate>(results);
Your C# class model does not match the incoming JSON data structure. Rates is an array of items, but you're treating it like a string in your C# model. Timestamp is a number but you're treating it like a string in your C# model.
public class ExchangeRate
{
public string Disclaimer { get; set; }
public string License { get; set; }
public int Timestamp { get; set; }
public string Base { get; set; }
public Dictionary<string, double> Rates { get; set; }
}
​Using VS 2019, Dot Net Core, Azure Function. HttpTrigger.
I've worked with JSON files previously in .Net Desktop and Server app dev. So, don't know what's happening in Azure and with Newtonsoft. When I try and dump the value of wht.YourName.last, I get the error,
Object reference not set to an instance of an object
which confuses me because in my other programming with System.Text.Json, if I have a class model for a JSON file structure that has a child, the usual function call I use, which is JsonSerializer.Deserialize<jsonclass>(jsonstring), it has no problem setting up the child of the parent parent (reference below, class structure).
Is there a difference between the two function implementations, JsonConvert.DeserializeObject and JsonSerializer.Deserialize?
All of the code samples I've seen seem for Newtonsoft's method seem straight forward as its counterpart in dot net, which doesn't require me to have to do any pre-initalization of the NameBlock class/object.
Hope I explained that well enough considering my brain is kind of fried learning Azure.
Here is my deserialization code using Newtonsoft's method:
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
WebhookTest wht = JsonConvert.DeserializeObject<WebhookTest>(requestBody);
Raw dump of httprequest.Body:
{
"FormID":"1081011",
"UniqueID":"178165183",
"support_request":"",
"your_name":{
"first":"Testy",
"last":"Tester"
},
"email":"jxxxx#gxxxcxxxaxxxxxxxx.com",
"phone":"(111) 867-5309",
"upload_a_file_optional":"",
"request_details":"Testing latest revision of Azure function that deserializes JSON data into a class object."
}
This is what my class structure looks like:
public class NameBlock
{
public string first { get; set; }
public string last { get; set; }
}
public class WebhookTest
{
public string FormID { get; set; }
public string UniqueID { get; set; }
public string SupportRequest { get; set; }
public NameBlock YourName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
[JsonProperty("Uploadafile(optional)")]
public string UploadafileOptional { get; set; }
public string RequestDetails { get; set; }
}
The reason for the error Object reference not set to an instance of an object is the code can't find wht.YourName(because wht.YourName is null). Please change your class structure to:
public class NameBlock
{
public string first { get; set; }
public string last { get; set; }
}
public class WebhookTest
{
public string FormID { get; set; }
public string UniqueID { get; set; }
public string SupportRequest { get; set; }
[JsonProperty(PropertyName = "your_name")]
public NameBlock YourName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
[JsonProperty("Uploadafile(optional)")]
public string UploadafileOptional { get; set; }
public string RequestDetails { get; set; }
}
Just add a line [JsonProperty(PropertyName = "your_name")]
By the way:
When we use System.Text.Json, it will relate your_name(in request json) with YourName(in class structure) automatically according to hump law. But when we use Newtonsoft.Json, it can't do it. So it can't relate your_name with YourName. We need to add [JsonProperty(PropertyName = "your_name")] to let the code know how to relate the two properties.
I'm trying to create multiple objects out of a JSON result.
My JSON looks like that:
EDIT
[{"quality":"hd","type":"video/mp4","width":1920,"height":1080,"link":"http://player.vimeo.com/external/255898412.hd.mp4?s=8766561d230749d75a0ddde2ddfbeb69e0e5198e&profile_id=175&oauth2_token_id=1040381751","created_time":"2018-02-15T15:46:25+02:00","fps":23.98,"size":3113207678,"md5":"b6beed65b699df870e481045178accc5","link_secure":"https://player.vimeo.com/external/255898412.hd.mp4?s=8766561d230749d75a0ddde2ddfbeb69e0e5198e&profile_id=175&oauth2_token_id=1040381751"},{"quality":"sd","type":"video/mp4","width":640,"height":360,"link":"http://player.vimeo.com/external/255898412.sd.mp4?s=b51b55f6bd6e1af2a8f48571e5804d91e6a82533&profile_id=164&oauth2_token_id=1040381751","created_time":"2018-02-15T15:46:05+02:00","fps":23.98,"size":536864946,"md5":"af227a5526af15d2bce6ac951d6cf06b","link_secure":"https://player.vimeo.com/external/255898412.sd.mp4?s=b51b55f6bd6e1af2a8f48571e5804d91e6a82533&profile_id=164&oauth2_token_id=1040381751"},{"quality":"sd","type":"video/mp4","width":960,"height":540,"link":"http://player.vimeo.com/external/255898412.sd.mp4?s=b51b55f6bd6e1af2a8f48571e5804d91e6a82533&profile_id=165&oauth2_token_id=1040381751","created_time":"2018-02-15T15:46:05+02:00","fps":23.98,"size":1242328160,"md5":"1963f908509b14fd7a40dc46bfa6c519","link_secure":"https://player.vimeo.com/external/255898412.sd.mp4?s=b51b55f6bd6e1af2a8f48571e5804d91e6a82533&profile_id=165&oauth2_token_id=1040381751"},{"quality":"hd","type":"video/mp4","width":1280,"height":720,"link":"http://player.vimeo.com/external/255898412.hd.mp4?s=8766561d230749d75a0ddde2ddfbeb69e0e5198e&profile_id=174&oauth2_token_id=1040381751","created_time":"2018-02-15T15:46:05+02:00","fps":23.98,"size":1977386604,"md5":"af38f067bd39f4f5bb71bad72f925337","link_secure":"https://player.vimeo.com/external/255898412.hd.mp4?s=8766561d230749d75a0ddde2ddfbeb69e0e5198e&profile_id=174&oauth2_token_id=1040381751"},{"quality":"hls","type":"video/mp4","link":"https://player.vimeo.com/external/255898412.m3u8?s=f25b7114977a0c6b37739886da189051ed31999e&oauth2_token_id=1040381751","created_time":"2018-02-15T15:46:25+02:00","fps":23.98,"size":3113207678,"md5":"b6beed65b699df870e481045178accc5","link_secure":"https://player.vimeo.com/external/255898412.m3u8?s=f25b7114977a0c6b37739886da189051ed31999e&oauth2_token_id=1040381751"}]
it should be parsed into 3 objects.
I got a VideoFileModel.cs class that looks like that:
public partial class VideoFileModel
{
[JsonProperty("quality")]
public string Quality { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("width")]
public long? Width { get; set; }
[JsonProperty("height")]
public long? Height { get; set; }
[JsonProperty("link")]
public string Link { get; set; }
[JsonProperty("created_time")]
public System.DateTime CreatedTime { get; set; }
[JsonProperty("fps")]
public double Fps { get; set; }
[JsonProperty("size")]
public long Size { get; set; }
[JsonProperty("md5")]
public string Md5 { get; set; }
[JsonProperty("link_secure")]
public string LinkSecure { get; set; }
}
What I'm trying to do at the moment, is parsing it like that:
string json = Helpers.HTTPFetch(url, method, headers, body, contentType);
var result = JsonConvert.DeserializeObject<VideoFileModel>(json);
but I'm pretty sure it's not working, or at least not in the way I want it to work.
what should I change?
You should simply use List<> when deserializing :
var result = JsonConvert.DeserializeObject<List<VideoFileModel>>(json);
There are is a list of VideoFileModel in your JSON that you trying to deserialize into a single object.
Following gets deserialized:
UPDATE:
As per OP updated JSON. It still gets deserialized:
I have no previous experience with JSON or using web services, however I'm trying to consume a web service that returns meteorological information.
Here's the documentation on the API that I'm trying to use.
This API gives me data serialized with JSON. I did some reading into JSON, and from what I understand, the best way to access this serialized data after I download it would be to de-serialize it into an object with matching properties and types. Did I get this part right? I don't understand however in this case how am I supposed to accurately know the types of the data returned via JSON.
In the API that I mentioned before I got this example of a response from the API in JSON:
{"coord":
{"lon":145.77,"lat":-16.92},
"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04n"}],
"base":"cmc stations",
"main":{"temp":293.25,"pressure":1019,"humidity":83,"temp_min":289.82,"temp_max":295.37},
"wind":{"speed":5.1,"deg":150},
"clouds":{"all":75},
"rain":{"3h":3},
"dt":1435658272,
"sys":{"type":1,"id":8166,"message":0.0166,"country":"AU","sunrise":1435610796,"sunset":1435650870},
"id":2172797,
"name":"Cairns",
"cod":200}
What I did was, on Visual Studio I used the "Paste Special" > "Paste as JSON classes" option, which created these classes for me:
public class Rootobject
{
public Coord coord { get; set; }
public Weather[] weather { get; set; }
public string _base { get; set; }
public Main main { get; set; }
public Wind wind { get; set; }
public Clouds clouds { get; set; }
public Rain rain { 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 float lon { get; set; }
public float lat { get; set; }
}
public class Main
{
public float temp { get; set; }
public int pressure { get; set; }
public int humidity { get; set; }
public float temp_min { get; set; }
public float temp_max { get; set; }
}
public class Wind
{
public float speed { get; set; }
public int deg { get; set; }
}
public class Clouds
{
public int all { get; set; }
}
public class Rain
{
public int _3h { get; set; }
}
public class Sys
{
public int type { get; set; }
public int id { get; set; }
public float message { get; set; }
public string country { get; set; }
public int sunrise { get; set; }
public int sunset { 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; }
}
The problem is that when I request data using the HttpClient, when I try to de-serialize the response I get I few errors regarding mismatching data types, like for example, float data being assign to properties of the type int.
Here's a snippet of my code:
string json = await client.GetStringAsync("weather?q=London,uk&appid=010101010101010101101");
Rootobject currentWeather = new Rootobject();
currentWeather = JsonConvert.DeserializeObject<Rootobject>(json);
MessageBox.Show(currentWeather.name);
I understand that in this case I could change the types of the properties in my classes to match what is being returned by the API, however that doesn't feel right to me, mainly because seems like it could be a source of troubles and unpredictable behavior. Am I doing this right? Maybe I'm missing something in the API documentation, shouldn't they provide the type of the data being returned?
Correct : De-serialize it into an object with matching properties and types.
First check the API documentation for the types, and if that is not comprehensiive enough I would consider changing your types to match what you infer from the JSON.
A value of 289.9 is a float.
A value of 1435650870 can be stored an int.
A value of AU can be a string/enum.
Edit:
I checked the API documentation you linked to and don't see anywhere were it explicitly states the types of data returned.
Edit 2:
Answering your question more directly, "how am I supposed to accurately know the types of the data returned via JSON?" (thanks #CodeCaster), without finding that information in documentation I don't think you can.
But I feel you can get 99.999% close by just looking at historical data returned.
If it is satisfied for you to use dynamic you can try this snippet
string json = await client.GetStringAsync("weather?q=London,uk&appid=010101010101010101101");
dynamic currentWeather= JObject.Parse(json);
MessageBox.Show(currentWeather.name);
You will find more details in documentation
I'm writing here because I think I used all resources I could get. There must be something terribly wrong with my abstraction/approach because I cannot
make it work properly. Task is quite simple - I need to iterate through nested list(??) generated from json input(or maybe I'm doing it wrong from the scratch).
Using jquery with this json works great but this time I need to process data on the server side.
I got json input(example extract below):
{
"services":[
{
"service_status":"CRITICAL",
"service_host":{
"host_status":2,
"host_address":"192.168.1.12",
"host_name":"test1app_srv",
"host_problem_has_been_acknowledged":0,
"host_has_comments":0,
"host_notifications_enabled":1,
"host_checks_enabled":1,
"host_is_flapping":0,
"host_scheduled_downtime_depth":0,
"host_notes_url":"",
"host_action_url":"",
"host_icon_image":"server.gif"
},
"service_description":"test1app_srv",
"service_problem_has_been_acknowledged":0,
"service_has_comments":0,
"service_accept_passive_service_checks":1,
"service_notifications_enabled":1,
"service_checks_enabled":1,
"service_is_flapping":0,
"service_scheduled_downtime_depth":0,
"service_notes_url":"",
"service_action_url":"",
"service_icon_image":"services.gif",
"service_state_duration":" 0d 0h 2m 7s",
"service_last_check":"04-27-2013 23:49:55",
"service_current_attempt":1,
"service_max_attempts":1,
"service_plugin_output":"CRITICAL - Throughput : Threshold '600' failed for value 720"
},
{}
]
}
from which, using http://json2csharp.com/ I've generated c# classes:
public class ServiceHost
{
public int host_status { get; set; }
public string host_address { get; set; }
public string host_name { get; set; }
public int host_problem_has_been_acknowledged { get; set; }
public int host_has_comments { get; set; }
public int host_notifications_enabled { get; set; }
public int host_checks_enabled { get; set; }
public int host_is_flapping { get; set; }
public int host_scheduled_downtime_depth { get; set; }
public string host_notes_url { get; set; }
public string host_action_url { get; set; }
public string host_icon_image { get; set; }
}
public class Service
{
public string service_status { get; set; }
public ServiceHost service_host { get; set; }
public string service_description { get; set; }
public int service_problem_has_been_acknowledged { get; set; }
public int service_has_comments { get; set; }
public int service_accept_passive_service_checks { get; set; }
public int service_notifications_enabled { get; set; }
public int service_checks_enabled { get; set; }
public int service_is_flapping { get; set; }
public int service_scheduled_downtime_depth { get; set; }
public string service_notes_url { get; set; }
public string service_action_url { get; set; }
public string service_icon_image { get; set; }
public string service_state_duration { get; set; }
public string service_last_check { get; set; }
public int service_current_attempt { get; set; }
public int service_max_attempts { get; set; }
public string service_plugin_output { get; set; }
}
public class NagiosRootObject
{
public List<Service> services { get; set; }
}
I managed to get the NagiosRootObject.services content but I cannot access values from Service.service_host.
I focused on an approach utilizing
NagiosRootObject obj = JsonConvert.DeserializeObject<NagiosRootObject>(json);
I have all above and I'm using Json.NET from http://json.codeplex.com.
I have tried hints from
Deserializing JSON object into a C# list
Deserialize JSON array(or list) in C#
C# - How to implement IEnumerator on a class
Deserialize Json to Class that implements Ienumerable in Asp.net
and few related but witho no luck.
Knowing that there is so many tutorials and not being able to make use of it makes me really sad..
Help would be appreciated. This post is the last resort for this task... I need serious tips. Thank You
Using json.NET the following code works: (after putting your json in a file called 'json.txt')
using (var reader = File.OpenText("json.txt"))
{
var ser = JsonSerializer.Create(null);
var jReader = new JsonTextReader(reader);
var grp = ser.Deserialize<NagiosRootObject>(jReader);
}
However, the list is populated by two objects, and in the 2nd one all the values are null. This is because you have an empty element {} in your json.
Edit: Your code works just as well in my test, so no need to change it.
Have you tried:
var obj = new JavaScriptSerializer().Deserialize<NagiosRootObject>(jsonString);
If you want to parse this json in server then it is better to parse this json into XML and utilize that xml to traverse. In server side coding xml traversing is easy. Especially in C#.
Convert the json into XMl or wise versa using newtonsoft dll. The code to parse json to XMl is
XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json);
Dpwnload the dll from the link
http://json.codeplex.com/
I hope this will help you.