I am relatively new to JSON and using an API forecast.io. It returns the JSON below, which I need to parse.
"daily":{
"summary":"Drizzle on Monday and Tuesday, with temperatures bottoming out at 91°F on Monday.","icon":"rain",
"data":[{
"time":1463770800,"summary":"Clear throughout the day.","icon":"clearday","sunriseTime":1463788956,"sunsetTime":1463839653,"moonPhase":0.48,"precipIntensity":0,"precipIntensityMax":0,"precipProbability":0,"temperatureMin":63.06,"temperatureMinTime":1463785200,"temperatureMax":95.23,"temperatureMaxTime":1463824800,"apparentTemperatureMin":63.06,"apparentTemperatureMinTime":1463785200,"apparentTemperatureMax":90.3,"apparentTemperatureMaxTime":1463824800,"dewPoint":37.34,"humidity":0.25,"windSpeed":3.44,"windBearing":22,"cloudCover":0,"pressure":1002.14,"ozone":283.7}
I extracted the "daily" portion successfully, but I could not get the "data" inside the "daily". I need to have the details, i.e. summary, time, icon, etc. I'd really appreciate some help.
Here is my C# code:
var test = new System.Net.WebClient().DownloadString("https://api.forecast.io/forecast/f2857958690caafc67d0dfba402c1f57/" + Latitude + "," + Longitude);
var json = JObject.Parse(test);
var daily = json.ToObject<DailyWeatherDTO>();
public class DailyWeatherDTO
{
public DailyWeatherData daily { get; set; }
}
public class DailyWeatherData
{
public daily data { get; set; }
}
public class daily
{
public string time { get; set; }
public String summary { get; set; }
public String icon { get; set; }
public String precipIntensity { get; set; }
public String precipProbability { get; set; }
public string sunriseTime { get; set; }
public string sunsetTime { get; set; }
public string moonPhase { get; set; }
public string precipIntensityMax { get; set; }
public string temperatureMin { get; set; }
public string temperatureMinTime { get; set; }
public string temperatureMax { get; set; }
public string temperatureMaxTime { get; set; }
public string apparentTemperatureMin { get; set; }
public string apparentTemperatureMinTime { get; set; }
public string apparentTemperatureMax { get; set; }
public string apparentTemperatureMaxTime { get; set; }
public string dewPoint { get; set; }
public string humidity { get; set; }
public string windSpeed { get; set; }
public string windBearing { get; set; }
public string cloudCover { get; set; }
public string pressure { get; set; }
public string ozone { get; set; }
}
First of all, the JSON you posted is not valid as shown. Specifically, you are missing a closing square bracket and curly brace at the end; plus, the whole thing needs to be enclosed in another pair of curly braces to be valid. Here is the corrected version, reformatted for readability:
{
"daily": {
"summary": "Drizzle on Monday and Tuesday, with temperatures bottoming out at 91°F on Monday.",
"icon": "rain",
"data": [
{
"time": 1463770800,
"summary": "Clear throughout the day.",
"icon": "clearday",
"sunriseTime": 1463788956,
"sunsetTime": 1463839653,
"moonPhase": 0.48,
"precipIntensity": 0,
"precipIntensityMax": 0,
"precipProbability": 0,
"temperatureMin": 63.06,
"temperatureMinTime": 1463785200,
"temperatureMax": 95.23,
"temperatureMaxTime": 1463824800,
"apparentTemperatureMin": 63.06,
"apparentTemperatureMinTime": 1463785200,
"apparentTemperatureMax": 90.3,
"apparentTemperatureMaxTime": 1463824800,
"dewPoint": 37.34,
"humidity": 0.25,
"windSpeed": 3.44,
"windBearing": 22,
"cloudCover": 0,
"pressure": 1002.14,
"ozone": 283.7
}
]
}
}
To be able to get all the data, your class structure needs to match the structure of the JSON. Assuming the above represents the complete JSON, here is what your classes should look like. In particular, notice the data property of the DailyWeatherData class is defined as a list of items (not a single object), which corresponds to the square brackets for the data property in the JSON.
public class DailyWeatherDTO // root-level container object
{
public DailyWeatherData daily { get; set; }
}
public class DailyWeatherData
{
public string summary { get; set; }
public string icon { get; set; }
public List<WeatherItem> data { get; set; }
}
public class WeatherItem
{
public int time { get; set; }
public string summary { get; set; }
public string icon { get; set; }
public int sunriseTime { get; set; }
public int sunsetTime { get; set; }
public double moonPhase { get; set; }
public int precipIntensity { get; set; }
public int precipIntensityMax { get; set; }
public int precipProbability { get; set; }
public double temperatureMin { get; set; }
public int temperatureMinTime { get; set; }
public double temperatureMax { get; set; }
public int temperatureMaxTime { get; set; }
public double apparentTemperatureMin { get; set; }
public int apparentTemperatureMinTime { get; set; }
public double apparentTemperatureMax { get; set; }
public int apparentTemperatureMaxTime { get; set; }
public double dewPoint { get; set; }
public double humidity { get; set; }
public double windSpeed { get; set; }
public int windBearing { get; set; }
public int cloudCover { get; set; }
public double pressure { get; set; }
public double ozone { get; set; }
}
With this class structure, you can deserialize the JSON like this:
DailyWeatherDTO dto = JsonConvert.DeserializeObject<DailyWeatherDTO>(json);
Here is a demo: https://dotnetfiddle.net/YTBrac
Related
been a while since I posted here. I'm working on an app and need to fetch statistics for a particular video using JSON (C#, UWP).
I already have the statistics as a JSON string but can't seem to parse them properly using Newtonsoft. The value always comes back null. This is my code:
var url = "https://www.googleapis.com/youtube/v3/videos?id=" + videoId + "&key=" + cl.googleAPIKey + "&part=snippet,contentDetails,statistics,status";
var http = new HttpClient();
var response = await http.GetStringAsync(url);
var statistics = JsonConvert.DeserializeObject<Statistics>(response);
string totalViews = statistics.viewCount;
The classes generated by Json2CSharp are:
public class PageInfo
{
public int totalResults { get; set; }
public int resultsPerPage { get; set; }
}
public class Default
{
public string url { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class Medium
{
public string url { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class High
{
public string url { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class Standard
{
public string url { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class Maxres
{
public string url { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class Thumbnails
{
public Default #default { get; set; }
public Medium medium { get; set; }
public High high { get; set; }
public Standard standard { get; set; }
public Maxres maxres { get; set; }
}
public class Localized
{
public string title { get; set; }
public string description { get; set; }
}
public class Snippet
{
public DateTime publishedAt { get; set; }
public string channelId { get; set; }
public string title { get; set; }
public string description { get; set; }
public Thumbnails thumbnails { get; set; }
public string channelTitle { get; set; }
public List<string> tags { get; set; }
public string categoryId { get; set; }
public string liveBroadcastContent { get; set; }
public Localized localized { get; set; }
}
public class ContentDetails
{
public string duration { get; set; }
public string dimension { get; set; }
public string definition { get; set; }
public string caption { get; set; }
public bool licensedContent { get; set; }
public string projection { get; set; }
}
public class Status
{
public string uploadStatus { get; set; }
public string privacyStatus { get; set; }
public string license { get; set; }
public bool embeddable { get; set; }
public bool publicStatsViewable { get; set; }
}
public class Statistics
{
public string viewCount { get; set; }
public string likeCount { get; set; }
public string dislikeCount { get; set; }
public string favoriteCount { get; set; }
public string commentCount { get; set; }
}
public class Item
{
public string kind { get; set; }
public string etag { get; set; }
public string id { get; set; }
public Snippet snippet { get; set; }
public ContentDetails contentDetails { get; set; }
public Status status { get; set; }
public Statistics statistics { get; set; }
}
public class RootObject
{
public string kind { get; set; }
public string etag { get; set; }
public PageInfo pageInfo { get; set; }
public List<Item> items { get; set; }
}
As I say the value will always come back as null regardless of the video ID.
Does anyone have any ideas?
Thanks
You are deserializing to the wrong class. Json2Csharp generated many classes, but Statistics is way down the tree. You should deserialize the RootObject instead:
var root = JsonConvert.DeserializeObject<RootObject>( response );
And then navigate to the statistics within the resulting class structure like for example:
foreach ( var statistics in root.Items.Select( i => i.Statistics) )
{
//do something
}
I am working a Xamarin.Forms App that uses the Azure Face API. With this API you retrieve a JSON response (See Below).
I want to extract the gender of the person in the image but am having trouble with it as I am very new to this.
I extract the full JSON response into a string but I would like to be able to extract data such as the 'Gender' or the 'Age' of the person in the image.
[{"faceId":"9448dfe4-afb6-4557-94fe-010fc439ff36","faceRectangle":{"top":635,"left":639,"width":789,"height":789},"faceAttributes":{"smile":0.187,"headPose":{"pitch":0.0,"roll":-1.6,"yaw":-7.9},"gender":"male","age":34.6,"facialHair":{"moustache":0.5,"beard":0.6,"sideburns":0.6},"glasses":"NoGlasses","emotion":{"anger":0.0,"contempt":0.69,"disgust":0.0,"fear":0.0,"happiness":0.187,"neutral":0.12,"sadness":0.002,"surprise":0.0},"blur":{"blurLevel":"low","value":0.15},"exposure":{"exposureLevel":"overExposure","value":0.85},"noise":{"noiseLevel":"medium","value":0.42},"makeup":{"eyeMakeup":false,"lipMakeup":false},"accessories":[],"occlusion":{"foreheadOccluded":false,"eyeOccluded":false,"mouthOccluded":false},"hair":{"bald":0.02,"invisible":false,"hairColor":[{"color":"brown","confidence":1.0},{"color":"black","confidence":0.95},{"color":"other","confidence":0.22},{"color":"blond","confidence":0.11},{"color":"gray","confidence":0.05},{"color":"red","confidence":0.04}]}}}]
This is how I set the JSON data to a string.
string contentString = await response.Content.ReadAsStringAsync();
You usually want to create a class that represents your response e. g. Person. Then you could use the Newtonsoft.Json nuget package to deserialize the object.:
var person = JsonConvert.DeserializeObject<Person>(contentString);
Now you can access the values like:
person.Gender
Using Newtonsoft.Json:
var results = JsonConvert.DeserializeObject<AzureFace>(contentString);
Debug.WriteLine(results.faceAttributes.age);
C# Model Used (via http://jsonutils.com)
public class FaceRectangle
{
public int top { get; set; }
public int left { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class HeadPose
{
public double pitch { get; set; }
public double roll { get; set; }
public double yaw { get; set; }
}
public class FacialHair
{
public double moustache { get; set; }
public double beard { get; set; }
public double sideburns { get; set; }
}
public class Emotion
{
public double anger { get; set; }
public double contempt { get; set; }
public double disgust { get; set; }
public double fear { get; set; }
public double happiness { get; set; }
public double neutral { get; set; }
public double sadness { get; set; }
public double surprise { get; set; }
}
public class Blur
{
public string blurLevel { get; set; }
public double value { get; set; }
}
public class Exposure
{
public string exposureLevel { get; set; }
public double value { get; set; }
}
public class Noise
{
public string noiseLevel { get; set; }
public double value { get; set; }
}
public class Makeup
{
public bool eyeMakeup { get; set; }
public bool lipMakeup { get; set; }
}
public class Occlusion
{
public bool foreheadOccluded { get; set; }
public bool eyeOccluded { get; set; }
public bool mouthOccluded { get; set; }
}
public class HairColor
{
public string color { get; set; }
public double confidence { get; set; }
}
public class Hair
{
public double bald { get; set; }
public bool invisible { get; set; }
public IList<HairColor> hairColor { get; set; }
}
public class FaceAttributes
{
public double smile { get; set; }
public HeadPose headPose { get; set; }
public string gender { get; set; }
public double age { get; set; }
public FacialHair facialHair { get; set; }
public string glasses { get; set; }
public Emotion emotion { get; set; }
public Blur blur { get; set; }
public Exposure exposure { get; set; }
public Noise noise { get; set; }
public Makeup makeup { get; set; }
public IList<object> accessories { get; set; }
public Occlusion occlusion { get; set; }
public Hair hair { get; set; }
}
public class AzureFace
{
public string faceId { get; set; }
public FaceRectangle faceRectangle { get; set; }
public FaceAttributes faceAttributes { get; set; }
}
I'm trying to deserialize some JSON code in a c# applicatie. I use the DataContractJsonSerializer class to do this. All works fine, until I get nested jsonobjects,
I recieve the following json from an external API:
[{"name":"Beeldscherm","json":"{\"onHomeEnter\":{\"state\":0,\"delay\":0,\"fadeTime\":0,\"active\":false,\"updatedAt\":1487166732440},\"onHomeExit\":{\"state\":0,\"delay\":120,\"fadeTime\":0,\"active\":false,\"updatedAt\":1487163669388},\"onRoomEnter\":{\"state\":1,\"delay\":0,\"fadeTime\":0,\"active\":false,\"updatedAt\":1},\"onRoomExit\":{\"state\":0,\"delay\":120,\"fadeTime\":0,\"active\":false,\"updatedAt\":1},\"onNear\":{\"state\":1,\"delay\":0,\"fadeTime\":0,\"active\":false,\"updatedAt\":1487164911729},\"onAway\":{\"state\":0,\"delay\":2,\"fadeTime\":0,\"active\":false,\"updatedAt\":1487164909184}}","id":"58a44fa04f40b016004ffca2","sphereId":"58a44c0a4f40b016004ffc9d","createdAt":"2017-02-15T13:52:12.783Z","updatedAt":"2017-02-15T12:55:05.332Z"}]
Which I edit with the following code:
responJsonText = responJsonText.Replace("\\", "").Replace("\"{", "{").Replace("}\"", "}");
and it then looks like this:
[{"name":"Beeldscherm","json":{"onHomeEnter":{"state":0,"delay":0,"fadeTime":0,"active":false,"updatedAt":1487166732440},"onHomeExit":{"state":0,"delay":120,"fadeTime":0,"active":false,"updatedAt":1487163669388},"onRoomEnter":{"state":1,"delay":0,"fadeTime":0,"active":false,"updatedAt":1},"onRoomExit":{"state":0,"delay":120,"fadeTime":0,"active":false,"updatedAt":1},"onNear":{"state":1,"delay":0,"fadeTime":0,"active":false,"updatedAt":1487164911729},"onAway":{"state":0,"delay":2,"fadeTime":0,"active":false,"updatedAt":1487164909184}},"id":"58a44fa04f40b016004ffca2","sphereId":"58a44c0a4f40b016004ffc9d","createdAt":"2017-02-15T13:52:12.783Z","updatedAt":"2017-02-15T12:55:05.332Z"}]
and try to parse this using the following classes:
[DataContract]
class Appliance
{
[DataMember]
public String name { get; set; }
[DataMember]
public ApplianceJson json { get; set; }
[DataMember]
public String id { get; set; }
[DataMember]
public String sphereId { get; set; }
[DataMember]
public String createdAt { get; set; }
[DataMember]
public String updatedAt { get; set; }
}
[DataContract]
class ApplianceJson
{
[DataMember]
public ApplianceEvents onHomeEnter { get; set; }
[DataMember]
public ApplianceEvents onHomeExit { get; set; }
[DataMember]
public ApplianceEvents onRoomEnter { get; set; }
[DataMember]
public ApplianceEvents onRoomExit { get; set; }
[DataMember]
public ApplianceEvents onNear { get; set; }
[DataMember]
public ApplianceEvents onAway { get; set; }
}
[DataContract]
class ApplianceEvents
{
[DataMember]
public int state { get; set; }
[DataMember]
public int delay { get; set; }
[DataMember]
public int fadeTime { get; set; }
[DataMember]
public bool active { get; set; }
[DataMember]
public int updatedAt { get; set; }
}
and the following code for the deserialization:
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<Appliance>));
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(responJsonText));
The error I get is:
Exception thrown: 'System.Runtime.Serialization.SerializationException' in System.Private.DataContractSerialization.dll
Exception thrown: 'System.Runtime.Serialization.SerializationException' in mscorlib.ni.dll
Does anybody see something that is wrong and how I could fix it?
Update
I checked the json string and its correct now, I've put the correct version in the question
Update 2
added the original JSON
if you notice the Original Json, You can see " is not \" but if you go deep into json, the Json Node itself has " as \". So i cleaned up all \" first and then again replaced " with \" Used Newtonsoft Json and then it parsed successfully. See my answer.
Using This Site and your JsonString, Below are the proper Json Class Structure that I created.
public class Appliance
{
public string name { get; set; }
public Json json { get; set; }
public string id { get; set; }
public string sphereId { get; set; }
public string createdAt { get; set; }
public string updatedAt { get; set; }
}
public class OnHomeEnter
{
public int state { get; set; }
public int delay { get; set; }
public int fadeTime { get; set; }
public bool active { get; set; }
public long updatedAt { get; set; }
}
public class OnHomeExit
{
public int state { get; set; }
public int delay { get; set; }
public int fadeTime { get; set; }
public bool active { get; set; }
public long updatedAt { get; set; }
}
public class OnRoomEnter
{
public int state { get; set; }
public int delay { get; set; }
public int fadeTime { get; set; }
public bool active { get; set; }
public int updatedAt { get; set; }
}
public class OnRoomExit
{
public int state { get; set; }
public int delay { get; set; }
public int fadeTime { get; set; }
public bool active { get; set; }
public int updatedAt { get; set; }
}
public class OnNear
{
public int state { get; set; }
public int delay { get; set; }
public int fadeTime { get; set; }
public bool active { get; set; }
public long updatedAt { get; set; }
}
public class OnAway
{
public int state { get; set; }
public int delay { get; set; }
public int fadeTime { get; set; }
public bool active { get; set; }
public long updatedAt { get; set; }
}
public class Json
{
public OnHomeEnter onHomeEnter { get; set; }
public OnHomeExit onHomeExit { get; set; }
public OnRoomEnter onRoomEnter { get; set; }
public OnRoomExit onRoomExit { get; set; }
public OnNear onNear { get; set; }
public OnAway onAway { get; set; }
}
Once Done, I used Json.Net
to Parse the JsonString to Appliance Object
Below is the Final Json String and Parser.
"[{\"name\":\"Beeldscherm\",\"json\":{\"onHomeEnter\":{\"state\":0,\"delay\":0,\"fadeTime\":0,\"active\":false,\"updatedAt\":1487166732440},\"onHomeExit\":{\"state\":0,\"delay\":120,\"fadeTime\":0,\"active\":false,\"updatedAt\":1487163669388},\"onRoomEnter\":{\"state\":1,\"delay\":0,\"fadeTime\":0,\"active\":false,\"updatedAt\":1},\"onRoomExit\":{\"state\":0,\"delay\":120,\"fadeTime\":0,\"active\":false,\"updatedAt\":1},\"onNear\":{\"state\":1,\"delay\":0,\"fadeTime\":0,\"active\":false,\"updatedAt\":1487164911729},\"onAway\":{\"state\":0,\"delay\":2,\"fadeTime\":0,\"active\":false,\"updatedAt\":1487164909184}},\"id\":\"58a44fa04f40b016004ffca2\",\"sphereId\":\"58a44c0a4f40b016004ffc9d\",\"createdAt\":\"2017 - 02 - 15T13: 52:12.783Z\",\"updatedAt\":\"2017 - 02 - 15T12: 55:05.332Z\"}]";
And Below is how I was able to successfully Parse Json.
List<Appliance> appJson = JsonConvert.DeserializeObject<List<Appliance>>(JsonData);
Good Luck.
Found an odd issue when trying to deserialize a JSON string into a C# Object. It "seems" to perform the operation successfully (as in it does not throw any exception etc), however the outputted POCO contains does not contain any data from the JSON string, it only contains type default data (nulls,"", 0 etc). I have tried this process with other JSON and it works fine.
private string GetJson()
{
return #"{""backdrop_path"":"" / 1LrtAhWPSEetJLjblXvnaYtl7eA.jpg"",""created_by"":[{""id"":488,""name"":""Steven Spielberg"",""profile_path"":"" / pOK15UNaw75Bzj7BQO1ulehbPPm.jpg""},{""id"":31,""name"":""Tom Hanks"",""profile_path"":"" / a14CNByTYALAPSGlwlmfHILpEIW.jpg""}],""episode_run_time"":[60],""first_air_date"":""2001 - 09 - 09"",""genres"":[{""id"":28,""name"":""Action""},{""id"":12,""name"":""Adventure""},{""id"":18,""name"":""Drama""},{""id"":10752,""name"":""War""}],""homepage"":""http://www.hbo.com/band-of-brothers"",""id"":4613,""in_production"":false,""languages"":[""de"",""fr"",""lt"",""nl"",""en""],""last_air_date"":""2001-11-04"",""name"":""Band of Brothers"",""networks"":[{""id"":49,""name"":""HBO""}],""number_of_episodes"":10,""number_of_seasons"":1,""origin_country"":[""GB"",""US""],""original_language"":""en"",""original_name"":""Band of Brothers"",""overview"":""Drawn from interviews with survivors of Easy Company, as well as their journals and letters, Band of Brothers chronicles the experiences of these men from paratrooper training in Georgia through the end of the war. As an elite rifle company parachuting into Normandy early on D-Day morning, participants in the Battle of the Bulge, and witness to the horrors of war, the men of Easy knew extraordinary bravery and extraordinary fear - and became the stuff of legend. Based on Stephen E. Ambrose's acclaimed book of the same name."",""popularity"":3.435181,""poster_path"":""/bUrt6oeXd04ImEwQjO9oLjRguaA.jpg"",""production_companies"":[{""name"":""DreamWorks SKG"",""id"":27},{""name"":""HBO Films"",""id"":7429},{""name"":""DreamWorks Television"",""id"":15258}],""seasons"":[{""air_date"":null,""episode_count"":4,""id"":14071,""poster_path"":""/bMN9iiSAdnmAjflREfCCH0TTNyQ.jpg"",""season_number"":0},{""air_date"":""2001-09-09"",""episode_count"":10,""id"":14070,""poster_path"":""/15SN18OVbYt12Wzttclh51Sz9m1.jpg"",""season_number"":1}],""status"":""Ended"",""type"":""Scripted"",""vote_average"":8.5,""vote_count"":47}";
}
[TestMethod]
public void DeserializeTmdbShowData_ValidShowData_ReturnDeserializedObject()
{
//Arrange
string jsonStream = GetJson();
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
//Act
var tmdbShowDetails = jsonSerializer.Deserialize<List<TmdbShowDetailsDto>>(jsonStream);
//Assert
Assert.IsNotNull(tmdbShowDetails);
Assert.IsNotNull(tmdbShowDetails.First().backdrop_path);
}
public class TmdbShowDetailsDto
{
public string backdrop_path { get; set; }
public Created_By[] created_by { get; set; }
public int[] episode_run_time { get; set; }
public string first_air_date { get; set; }
public Genre[] genres { get; set; }
public string homepage { get; set; }
public int id { get; set; }
public bool in_production { get; set; }
public string[] languages { get; set; }
public string last_air_date { get; set; }
public string name { get; set; }
public Network[] networks { get; set; }
public int number_of_episodes { get; set; }
public int number_of_seasons { get; set; }
public string[] origin_country { get; set; }
public string original_language { get; set; }
public string original_name { get; set; }
public string overview { get; set; }
public float popularity { get; set; }
public string poster_path { get; set; }
public Production_Companies[] production_companies { get; set; }
public Season[] seasons { get; set; }
public string status { get; set; }
public string type { get; set; }
public float vote_average { get; set; }
public int vote_count { get; set; }
}
public class Created_By
{
public int id { get; set; }
public string name { get; set; }
public string profile_path { get; set; }
}
public class Genre
{
public int id { get; set; }
public string name { get; set; }
}
public class Network
{
public int id { get; set; }
public string name { get; set; }
}
public class Production_Companies
{
public string name { get; set; }
public int id { get; set; }
}
public class Season
{
public string air_date { get; set; }
public int episode_count { get; set; }
public int id { get; set; }
public string poster_path { get; set; }
public int season_number { get; set; }
}
Any ideas - Im sure I have missed something glaringly obvious but I cannot see it. Using .NET 4.5
Help appreciated.
Cheers
I used http://json2csharp.com/, and the code is like this, so you should look at it.
public class Poster
{
public string full { get; set; }
public string medium { get; set; }
public string thumb { get; set; }
}
public class Fanart
{
public string full { get; set; }
public string medium { get; set; }
public string thumb { get; set; }
}
public class Images
{
public Poster poster { get; set; }
public Fanart fanart { get; set; }
}
public class Ids
{
public int trakt { get; set; }
public string slug { get; set; }
public int tvdb { get; set; }
public string imdb { get; set; }
public int tmdb { get; set; }
public int tvrage { get; set; }
}
public class Show
{
public string title { get; set; }
public string overview { get; set; }
public int year { get; set; }
public string status { get; set; }
public Images images { get; set; }
public Ids ids { get; set; }
}
public class Poster2
{
public string full { get; set; }
public string medium { get; set; }
public string thumb { get; set; }
}
public class Fanart2
{
public string full { get; set; }
public string medium { get; set; }
public string thumb { get; set; }
}
public class Images2
{
public Poster2 poster { get; set; }
public Fanart2 fanart { get; set; }
}
public class Ids2
{
public int trakt { get; set; }
public string slug { get; set; }
public string imdb { get; set; }
public int tmdb { get; set; }
}
public class Movie
{
public string title { get; set; }
public string overview { get; set; }
public int year { get; set; }
public Images2 images { get; set; }
public Ids2 ids { get; set; }
}
public class Headshot
{
public object full { get; set; }
public object medium { get; set; }
public object thumb { get; set; }
}
public class Images3
{
public Headshot headshot { get; set; }
}
public class Ids3
{
public int trakt { get; set; }
public string slug { get; set; }
public string imdb { get; set; }
public int tmdb { get; set; }
public int tvrage { get; set; }
}
public class Person
{
public string name { get; set; }
public Images3 images { get; set; }
public Ids3 ids { get; set; }
}
public class RootObject
{
public string type { get; set; }
public object score { get; set; }
public Show show { get; set; }
public Movie movie { get; set; }
public Person person { get; set; }
}
You can use Paste-Special Feature in your VS-IDE Paster JSON as Classes
public class Rootobject
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public string type { get; set; }
public object score { get; set; }
public Show show { get; set; }
public Movie movie { get; set; }
public Person person { get; set; }
}
public class Show
{
public string title { get; set; }
public string overview { get; set; }
public int year { get; set; }
public string status { get; set; }
public Images images { get; set; }
public Ids ids { get; set; }
}
public class Images
{
public Poster poster { get; set; }
public Fanart fanart { get; set; }
}
public class Poster
{
public string full { get; set; }
public string medium { get; set; }
public string thumb { get; set; }
}
public class Fanart
{
public string full { get; set; }
public string medium { get; set; }
public string thumb { get; set; }
}
public class Ids
{
public int trakt { get; set; }
public string slug { get; set; }
public int tvdb { get; set; }
public string imdb { get; set; }
public int tmdb { get; set; }
public int tvrage { get; set; }
}
public class Movie
{
public string title { get; set; }
public string overview { get; set; }
public int year { get; set; }
public Images1 images { get; set; }
public Ids1 ids { get; set; }
}
public class Images1
{
public Poster1 poster { get; set; }
public Fanart1 fanart { get; set; }
}
public class Poster1
{
public string full { get; set; }
public string medium { get; set; }
public string thumb { get; set; }
}
public class Fanart1
{
public string full { get; set; }
public string medium { get; set; }
public string thumb { get; set; }
}
public class Ids1
{
public int trakt { get; set; }
public string slug { get; set; }
public string imdb { get; set; }
public int tmdb { get; set; }
}
public class Person
{
public string name { get; set; }
public Images2 images { get; set; }
public Ids2 ids { get; set; }
}
public class Images2
{
public Headshot headshot { get; set; }
}
public class Headshot
{
public object full { get; set; }
public object medium { get; set; }
public object thumb { get; set; }
}
public class Ids2
{
public int trakt { get; set; }
public string slug { get; set; }
public string imdb { get; set; }
public int tmdb { get; set; }
public int tvrage { get; set; }
}
Look like you JSON string is not in correct format that you are trying to deserialize. For example i have not find show property in the C# class but it present in JSON.
So this issue I couldn't figure out in the night or early in the morning - it took me till this afternoon until I realised that I was had the wrong JSON!!, so no wonder it wasn't working! I got mixed up with a few different apis that provided JSON. Thanks to those who had pointed out that the class looks wrong, made me double check my code and realise the simplicity of this issue. Kinda needed some rubber ducking to spot the problem. Cheers
I am working on an integration with the Expedia API. I am relatively new to ServiceStack but have managed pretty well so far, however, I've hit an issue with the deserialization of a JSON response from the API which seems to be failing despite having JsConfig.ThrowOnDeserializationError enabled.
JsConfig.Reset();
JsConfig.ThrowOnDeserializationError = true;
var availability = _client.Get<ExpediaHotelRoomAvailability>("avail?" + querystring);
In order to see the API response I am working with please use the following request:
GET http://dev.api.ean.com/ean-services/rs/hotel/v3/avail?minorRev=26&cid=55505&apiKey=cbrzfta369qwyrm9t5b8y8kf&customerUserAgent=Mozilla%2f5.0+(Windows+NT+6.3%3b+WOW64)+AppleWebKit%2f537.36+(KHTML%2c+like+Gecko)+Chrome%2f35.0.1916.114+Safari%2f537.36&customerIpAddress=%3a%3a1&hotelId=135857&arrivalDate=06%2f07%2f2014&departureDate=06%2f20%2f2014&includeDetails=true&includeRoomImages=true&room1=2 HTTP/1.1
User-Agent: Fiddler
Content-Type: text/json
Host: dev.api.ean.com
Here is a typical response:
{
"HotelRoomAvailabilityResponse":{
"#size":"1",
"customerSessionId":"0ABAAA7A-D42E-2914-64D2-01C0F09040D8",
"hotelId":135857,
"arrivalDate":"06\/07\/2014",
"departureDate":"06\/20\/2014",
"hotelName":"La Quinta Inn and Suites Raleigh Cary",
"hotelAddress":"191 Crescent Commons",
"hotelCity":"Cary",
"hotelStateProvince":"NC",
"hotelCountry":"US",
"numberOfRoomsRequested":1,
"checkInInstructions":"",
"tripAdvisorRating":4.5,
"tripAdvisorReviewCount":189,
"tripAdvisorRatingUrl":"http:\/\/www.tripadvisor.com\/img\/cdsi\/img2\/ratings\/traveler\/4.5-12345-4.gif",
"HotelRoomResponse":{
"rateCode":14587,
"roomTypeCode":14587,
"rateDescription":"Standard Room, 1 King Bed",
"roomTypeDescription":"Standard Room, 1 King Bed",
"supplierType":"E",
"propertyId":67977,
"BedTypes":{
"#size":"1",
"BedType":{
"#id":"14",
"description":"1 king"
}
},
"smokingPreferences":"S,NS",
"rateOccupancyPerRoom":3,
"quotedOccupancy":2,
"minGuestAge":0,
"RateInfos":{
"#size":"1",
"RateInfo":{
"#priceBreakdown":"true",
"#promo":"false",
"#rateChange":"true",
"RoomGroup":{
"Room":{
"numberOfAdults":2,
"numberOfChildren":0,
"rateKey":"0214364d-6819-4631-aa97-a162c43e0297"
}
},
"ChargeableRateInfo":{
"#averageBaseRate":"109.61539",
"#averageRate":"109.61539",
"#commissionableUsdTotal":"1425.0",
"#currencyCode":"USD",
"#maxNightlyRate":"165.0",
"#nightlyRateTotal":"1425.0",
"#surchargeTotal":"229.19",
"#total":"1654.19",
"NightlyRatesPerRoom":{
"#size":"13",
"NightlyRate":[
{
"#baseRate":"90.0",
"#rate":"90.0",
"#promo":"false"
},
{
"#baseRate":"90.0",
"#rate":"90.0",
"#promo":"false"
},
{
"#baseRate":"100.0",
"#rate":"100.0",
"#promo":"false"
},
{
"#baseRate":"115.0",
"#rate":"115.0",
"#promo":"false"
},
{
"#baseRate":"115.0",
"#rate":"115.0",
"#promo":"false"
},
{
"#baseRate":"115.0",
"#rate":"115.0",
"#promo":"false"
},
{
"#baseRate":"165.0",
"#rate":"165.0",
"#promo":"false"
},
{
"#baseRate":"165.0",
"#rate":"165.0",
"#promo":"false"
},
{
"#baseRate":"90.0",
"#rate":"90.0",
"#promo":"false"
},
{
"#baseRate":"95.0",
"#rate":"95.0",
"#promo":"false"
},
{
"#baseRate":"95.0",
"#rate":"95.0",
"#promo":"false"
},
{
"#baseRate":"95.0",
"#rate":"95.0",
"#promo":"false"
},
{
"#baseRate":"95.0",
"#rate":"95.0",
"#promo":"false"
}
]
},
"Surcharges":{
"#size":"1",
"Surcharge":{
"#type":"TaxAndServiceFee",
"#amount":"229.19"
}
}
},
"cancellationPolicy":"We understand that sometimes your travel plans change. We do not charge a change or cancel fee. However, this property (La Quinta Inn and Suites Raleigh Cary) imposes the following penalty to its customers that we are required to pass on: Cancellations or changes made after 6:00 PM ((GMT-05:00) Eastern Time (US & Canada)) on Jun 6, 2014 are subject to a 1 Night Room & Tax penalty. The property makes no refunds for no shows or early checkouts.",
"CancelPolicyInfoList":{
"CancelPolicyInfo":[
{
"versionId":208699803,
"cancelTime":"18:00:00",
"startWindowHours":0,
"nightCount":1,
"currencyCode":"USD",
"timeZoneDescription":"(GMT-05:00) Eastern Time (US & Canada)"
},
{
"versionId":208778550,
"cancelTime":"18:00:00",
"startWindowHours":24,
"nightCount":0,
"currencyCode":"USD",
"timeZoneDescription":"(GMT-05:00) Eastern Time (US & Canada)"
}
]
},
"nonRefundable":false,
"rateType":"MerchantStandard",
"currentAllotment":0,
"guaranteeRequired":false,
"depositRequired":true,
"taxRate":229.19
}
},
"ValueAdds":{
"#size":"3",
"ValueAdd":[
{
"#id":"2048",
"description":"Free Wireless Internet"
},
{
"#id":"2",
"description":"Continental Breakfast"
},
{
"#id":"128",
"description":"Free Parking"
}
]
},
"deepLink":"https:\/\/travel.ian.com\/templates\/55505\/hotels\/135857\/book?lang=en&standardCheckin=06\/07\/2014&standardCheckout=06\/20\/2014&selectedPrice=1654.190000&supplierType=E&rateCode=14587&roomTypeCode=14587&roomsCount=1&rooms[0].adultsCount=2&rateKey=0214364d-6819-4631-aa97-a162c43e0297",
"RoomImages":{
"#size":"1",
"RoomImage":{
"url":"http:\/\/media.expedia.com\/hotels\/1000000\/70000\/68000\/67977\/67977_103_s.jpg"
}
}
}
}
}
A large part of the response is de-serialized fine except for all of the rate information which I am really interested in. No exceptions are thrown during the deserialization so I have little to go on in terms of tracking down the exact problem. To be more specific let's take the ChargeableRateInfo - all values contained within are either null or zero.
Here is my class I am trying to deserialize the response to:
namespace MyCustomNamespace
{
using System.Collections.Generic;
public class BedType
{
public string description { get; set; }
public string id { get; set; }
}
public class BedTypes
{
public BedType BedType { get; set; }
public int size { get; set; }
}
public class Room
{
public int numberOfAdults { get; set; }
public int numberOfChildren { get; set; }
public string rateKey { get; set; }
}
public class RoomGroup
{
public Room Room { get; set; }
}
public class NightlyRate
{
public string baseRate { get; set; }
public string promo { get; set; }
public string rate { get; set; }
}
public class NightlyRatesPerRoom
{
public List<NightlyRate> NightlyRate { get; set; }
public int size { get; set; }
}
public class Surcharge
{
public decimal amount { get; set; }
public string type { get; set; }
}
public class Surcharges
{
public Surcharge Surcharge { get; set; }
public int size { get; set; }
}
public class ChargeableRateInfo
{
public NightlyRatesPerRoom NightlyRatesPerRoom { get; set; }
public Surcharges Surcharges { get; set; }
public decimal averageBaseRate { get; set; }
public decimal averageRate { get; set; }
public decimal commissionableUsdTotal { get; set; }
public string currencyCode { get; set; }
public decimal maxNightlyRate { get; set; }
public decimal nightlyRateTotal { get; set; }
public decimal surchargeTotal { get; set; }
public decimal total { get; set; }
}
public class CancelPolicyInfo
{
public string cancelTime { get; set; }
public string currencyCode { get; set; }
public int nightCount { get; set; }
public int percent { get; set; }
public int startWindowHours { get; set; }
public string timeZoneDescription { get; set; }
public int versionId { get; set; }
}
public class CancelPolicyInfoList
{
public List<CancelPolicyInfo> CancelPolicyInfo { get; set; }
}
public class RateInfo
{
public CancelPolicyInfoList CancelPolicyInfoList { get; set; }
public ChargeableRateInfo ChargeableRateInfo { get; set; }
public RoomGroup RoomGroup { get; set; }
public string cancellationPolicy { get; set; }
public int currentAllotment { get; set; }
public bool depositRequired { get; set; }
public bool guaranteeRequired { get; set; }
public bool nonRefundable { get; set; }
public string priceBreakdown { get; set; }
public string promo { get; set; }
public string promoType { get; set; }
public string rateChange { get; set; }
public string rateType { get; set; }
public decimal taxRate { get; set; }
}
public class RateInfos
{
public RateInfo RateInfo { get; set; }
public int size { get; set; }
}
public class ValueAdd
{
public string description { get; set; }
public string id { get; set; }
}
public class ValueAdds
{
public List<ValueAdd> ValueAdd { get; set; }
public int size { get; set; }
}
public class RoomImage
{
public string url { get; set; }
}
public class RoomImages
{
public RoomImage RoomImage { get; set; }
public int size { get; set; }
}
public class HotelRoomResponse
{
public BedTypes BedTypes { get; set; }
public RateInfos RateInfos { get; set; }
public RoomImages RoomImages { get; set; }
public ValueAdds ValueAdds { get; set; }
public string deepLink { get; set; }
public int minGuestAge { get; set; }
public int propertyId { get; set; }
public int quotedOccupancy { get; set; }
public int rateCode { get; set; }
public string rateDescription { get; set; }
public int rateOccupancyPerRoom { get; set; }
public int roomTypeCode { get; set; }
public string roomTypeDescription { get; set; }
public string smokingPreferences { get; set; }
public string supplierType { get; set; }
}
public class HotelRoomAvailabilityResponse
{
public List<HotelRoomResponse> HotelRoomResponse { get; set; }
public string arrivalDate { get; set; }
public string checkInInstructions { get; set; }
public string customerSessionId { get; set; }
public string departureDate { get; set; }
public string hotelAddress { get; set; }
public string hotelCity { get; set; }
public string hotelCountry { get; set; }
public int hotelId { get; set; }
public string hotelName { get; set; }
public string hotelStateProvince { get; set; }
public int numberOfRoomsRequested { get; set; }
public int size { get; set; }
public decimal tripAdvisorRating { get; set; }
public string tripAdvisorRatingUrl { get; set; }
public int tripAdvisorReviewCount { get; set; }
}
public class ExpediaHotelRoomAvailability
{
public HotelRoomAvailabilityResponse HotelRoomAvailabilityResponse { get; set; }
}
}
Could this possibly have something to do with the # symbols in the JSON and if so how do I get around this?
You can handle the # symbols named fields by providing their name using a [DataMember(Name=...)] attribute.
Unfortunately this mean you have to provide a [DataContract] attribute on your DTO, which means all the properties then become opt-in. So all properties will need to have [DataMember] to be included, which makes the DTO less readable.
So your NightlyRate DTO becomes:
[DataContract]
public class NightlyRate
{
[DataMember(Name="#baseRate")]
public string baseRate { get; set; }
[DataMember(Name="#promo")]
public string promo { get; set; }
[DataMember(Name="#rate")]
public string rate { get; set; }
}
And NightlyRatesPerRoom would be:
[DataContract]
public class NightlyRatesPerRoom
{
[DataMember]
public List<NightlyRate> NightlyRate { get; set; }
[DataMember(Name="#size")]
public int size { get; set; }
}
Obviously you will have to mark up the other DTOs as appropriate. I hope that helps.