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.
Related
I am receiving json with dynamic one node based on sector like "DEL-BOM", "NYC-BOM".
trying to parse but body getting null.
I just add Dictionary and key as node and class as value but still not getting values in DeserializeObject.
{
"fareRule": {
"DEL-BOM": {
"fr": {
"NO_SHOW": {
"DEFAULT": {
"policyInfo": "If Cancelled within 6 hrs of scheduled departure only statutory taxes will be Refunded."
}
},
"DATECHANGE": {
"DEFAULT": {
"amount": 3000.00,
"additionalFee": 50.00,
"policyInfo": "__nls__Changes permitted 06 Hrs before scheduled departure __nls__ Within 06-96 hrs Rs 3,000 + Fare Difference __nls__ Before 96 hrs Rs 2,500 + Fare Difference",
"fcs": {
"CRFT": 9.00,
"ARF": 3000.00,
"ARFT": 150.00,
"CRF": 50.00
}
}
},
"CANCELLATION": {
"DEFAULT": {
"amount": 3500.00,
"additionalFee": 50.00,
"policyInfo": "__nls__Cancellation permitted 06 Hrs before scheduled departure __nls__ Within 06-96 hrs Rs 3,500 __nls__ Before 96 hrs Rs 3,000",
"fcs": {
"ACFT": 175.00,
"CCFT": 9.00,
"ACF": 3500.00,
"CCF": 50.00
}
}
},
"SEAT_CHARGEABLE": {
"DEFAULT": {
"policyInfo": "Paid Seat"
}
}
}
}
},
"status": {
"success": true,
"httpStatus": 200
}
}
this is my class
public class Response
{
public Dictionary<string, Fr> fareRule { get; set; }
public Status status { get; set; }
}
public class DEFAULT
{
public string policyInfo { get; set; }
public double amount { get; set; }
public double additionalFee { get; set; }
public Fcs fcs { get; set; }
}
public class NOSHOW
{
public DEFAULT DEFAULT { get; set; }
}
public class Fcs
{
public double ARFT { get; set; }
public double ARF { get; set; }
public double CRFT { get; set; }
public double CRF { get; set; }
public double CCF { get; set; }
public double ACF { get; set; }
public double CCFT { get; set; }
public double ACFT { get; set; }
}
public class DATECHANGE
{
public DEFAULT DEFAULT { get; set; }
}
public class CANCELLATION
{
public DEFAULT DEFAULT { get; set; }
}
public class SEATCHARGEABLE
{
public DEFAULT DEFAULT { get; set; }
}
public class Fr
{
public NOSHOW NO_SHOW { get; set; }
public DATECHANGE DATECHANGE { get; set; }
public CANCELLATION CANCELLATION { get; set; }
public SEATCHARGEABLE SEAT_CHARGEABLE { get; set; }
}
public class Sector
{
public Fr fr { get; set; }
}
public class FareRule
{
public Sector sector { get; set; }
}
public class Status
{
public bool success { get; set; }
public int httpStatus { get; set; }
}
I have tried based on Parse dynamic JSON
Key is converting but body or value is null.
try this, it was tested and working properly
var jsonDeserialized = JsonConvert.DeserializeObject<Data>(json);
classes
public class Data
{
public Dictionary<string,Dictionary<string, Mode>> fareRule { get; set; }
public Status status { get; set; }
}
public class Status
{
public bool? success { get; set; }
public int? httpStatus { get; set; }
}
public class DEFAULT
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string policyInfo { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public double? amount { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public double? additionalFee { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public Dictionary<string,double?> fcs { get; set; }
}
public class NOSHOW
{
public DEFAULT DEFAULT { get; set; }
}
public class DATECHANGE
{
public DEFAULT DEFAULT { get; set; }
}
public class CANCELLATION
{
public DEFAULT DEFAULT { get; set; }
}
public class SEATCHARGEABLE
{
public DEFAULT DEFAULT { get; set; }
}
public class Mode
{
public NOSHOW NO_SHOW { get; set; }
public DATECHANGE DATECHANGE { get; set; }
public CANCELLATION CANCELLATION { get; set; }
public SEATCHARGEABLE SEAT_CHARGEABLE { get; set; }
}
Use Newtonsoft.Json for deserialization
Your Correct Model is.
public class DATECHANGE
{
public DEFAULT DEFAULT { get; set; }
}
public class CANCELLATION
{
public DEFAULT DEFAULT { get; set; }
}
public class SEATCHARGEABLE
{
public DEFAULT DEFAULT { get; set; }
}
public class Fr
{
public NOSHOW NO_SHOW { get; set; }
public DATECHANGE DATECHANGE { get; set; }
public CANCELLATION CANCELLATION { get; set; }
public SEATCHARGEABLE SEAT_CHARGEABLE { get; set; }
}
public class FareRule
{
[JsonProperty(PropertyName = "DEL-BOM")]
public DynamicBody DELBOM { get; set; }
[JsonProperty(PropertyName = "NYC-BOM")]
public DynamicBody NYCBOM { get; set; }
}
public class Status
{
public bool Success { get; set; }
public int HttpStatus { get; set; }
}
public class BaseResponseModel
{
public FareRule FareRule { get; set; }
public Status Status { get; set; }
}
public class DynamicBody
{
public Fr Fr { get; set; }
}
Then Deserialize like this code
var responseModel = JsonConvert.DeserializeObject<BaseResponseModel>(jsonStr);
I have made a class to deserialize stripe json response it works find but on some i am getting error :
Cannot convert null to a value type.
Even though i can see type is always there at the end.
This is the response:
{
"id": "evt_1Dezu4HJCcuwD0sbvkmV6bEb",
"object": "event",
"api_version": "2018-11-08",
"created": 1544252828,
"data": {
"object": {
"id": "sub_E7ExxxXGawn6cu",
"object": "subscription",
"application_fee_percent": null,
"billing": "charge_automatically",
"billing_cycle_anchor": 1544252827,
"cancel_at_period_end": false,
"canceled_at": null,
"created": 1544252827,
"current_period_end": 1544339227,
"current_period_start": 1544252827,
"customer": "cus_E7xxxQqowY9",
"days_until_due": null,
"default_source": null,
"discount": null,
"ended_at": null,
"items": {
"object": "list",
"data": [
{
"id": "si_E7EMDEdBnD6wUx",
"object": "subscription_item",
"created": 1544252828,
"metadata": {
},
"plan": {
"id": "plan_E5lRIPvrkNuRBB",
"object": "plan",
"active": true,
"aggregate_usage": null,
"amount": 0,
"billing_scheme": "per_unit",
"created": 1543997153,
"currency": "usd",
"interval": "day",
"interval_count": 1,
"livemode": false,
"metadata": {
},
"nickname": "Free Plan",
"product": "prod_E1CBxxxpNa5Lf02d",
"tiers": null,
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"quantity": 1,
"subscription": "sub_E7xxxXGawn6cu"
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/subscription_items?subscription=sub_E7xxxXGawn6cu"
},
"livemode": false,
"metadata": {
},
"plan": {
"id": "plan_E5lRIPxxxkNuRBB",
"object": "plan",
"active": true,
"aggregate_usage": null,
"amount": 0,
"billing_scheme": "per_unit",
"created": 1543997153,
"currency": "usd",
"interval": "day",
"interval_count": 1,
"livemode": false,
"metadata": {
},
"nickname": "Free Plan",
"product": "prod_E1CBZpNa5Lf02d",
"tiers": null,
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"quantity": 1,
"start": 1544252827,
"status": "active",
"tax_percent": null,
"trial_end": null,
"trial_start": null
}
},
"livemode": false,
"pending_webhooks": 1,
"request": {
"id": "req_OJV215KMm",
"idempotency_key": null
},
"type": "customer.subscription.created"
}
And class :
public class WebHookObjec
{
public int created { get; set; }
public bool livemode { get; set; }
public string id { get; set; }
public string #object { get; set; }
public object request { get; set; }
public string type { get; set; }
public int pending_webhooks { get; set; }
public string api_version { get; set; }
public Data data { get; set; }
public class Metadata
{
}
public class Plan
{
public string id { get; set; }
public string #object { get; set; }
public bool active { get; set; }
public object aggregate_usage { get; set; }
public int amount { get; set; }
public string billing_scheme { get; set; }
public int created { get; set; }
public string currency { get; set; }
public string interval { get; set; }
public int interval_count { get; set; }
public bool livemode { get; set; }
public Metadata metadata { get; set; }
public string nickname { get; set; }
public string product { get; set; }
public object tiers { get; set; }
public object tiers_mode { get; set; }
public object transform_usage { get; set; }
public int trial_period_days { get; set; }
public string usage_type { get; set; }
}
public class Phase
{
public object application_fee_percent { get; set; }
public object coupon { get; set; }
public int end_date { get; set; }
public List<Plan> plans { get; set; }
public int start_date { get; set; }
public object tax_percent { get; set; }
public bool trial { get; set; }
public object trial_end { get; set; }
}
public class PreviousAttributes
{
public string status { get; set; }
}
public class Object
{
public string id { get; set; }
public string #object { get; set; }
public string billing { get; set; }
public object canceled_at { get; set; }
public object completed_at { get; set; }
public int created { get; set; }
public object current_phase { get; set; }
public string customer { get; set; }
public object invoice_settings { get; set; }
public bool livemode { get; set; }
public List<Phase> phases { get; set; }
public object released_at { get; set; }
public object released_subscription { get; set; }
public string renewal_behavior { get; set; }
public object renewal_interval { get; set; }
public string revision { get; set; }
public string status { get; set; }
public object subscription { get; set; }
public Plan plan { get; set; }
public int quantity { get; set; }
public int start { get; set; }
public object tax_percent { get; set; }
public int trial_end { get; set; }
public int trial_start { get; set; }
public int amount { get; set; }
public int amount_refunded { get; set; }
public object application { get; set; }
public object application_fee { get; set; }
public string balance_transaction { get; set; }
public bool captured { get; set; }
public string currency { get; set; }
public string description { get; set; }
public object destination { get; set; }
public object dispute { get; set; }
public object failure_code { get; set; }
public object failure_message { get; set; }
public FraudDetails fraud_details { get; set; }
public object invoice { get; set; }
public Metadata metadata { get; set; }
public object on_behalf_of { get; set; }
public object order { get; set; }
public object outcome { get; set; }
public bool paid { get; set; }
public object payment_intent { get; set; }
public object receipt_email { get; set; }
public object receipt_number { get; set; }
public bool refunded { get; set; }
public Refunds refunds { get; set; }
public object review { get; set; }
public object shipping { get; set; }
public Source source { get; set; }
public object source_transfer { get; set; }
public object statement_descriptor { get; set; }
public object transfer_group { get; set; }
}
public class Data
{
public Object #object { get; set; }
public PreviousAttributes previous_attributes { get; set; }
}
public class FraudDetails
{
}
public class Refunds
{
public string #object { get; set; }
public List<object> data { get; set; }
public bool has_more { get; set; }
public int total_count { get; set; }
public string url { get; set; }
}
public class Metadata2
{
}
public class Source
{
public string id { get; set; }
public string #object { get; set; }
public object address_city { get; set; }
public object address_country { get; set; }
public object address_line1 { get; set; }
public object address_line1_check { get; set; }
public object address_line2 { get; set; }
public object address_state { get; set; }
public object address_zip { get; set; }
public object address_zip_check { get; set; }
public string brand { get; set; }
public string country { get; set; }
public string customer { get; set; }
public string cvc_check { get; set; }
public object dynamic_last4 { get; set; }
public int exp_month { get; set; }
public int exp_year { get; set; }
public string fingerprint { get; set; }
public string funding { get; set; }
public string last4 { get; set; }
public Metadata2 metadata { get; set; }
public string name { get; set; }
public object tokenization_method { get; set; }
}
}
After analyzing your json and class objects for json.
You json contains property with name "trial_period_days": null, has been null and you declare its respective property of type integer public int trial_period_days { get; set; } in Plan class object.
So int is a value type and cannot be cast to null.
To get rid from this exception you need to modify your property to either of below.
public object trial_period_days { get; set; }
OR
public int? trial_period_days { get; set; }
And same for your remaining properties inside Object class for trial_start and trial_end.
Note: Don't use Object as your custom class name because it already predefined class in .net framework.
Because there are some properties are null in your JSON data but you use value type to carry it.
You can try to use string type to represent your null value properties for those models to carry your JSON data.
public class Metadata
{
}
public class Metadata2
{
}
public class Plan
{
public string id { get; set; }
public string #string { get; set; }
public bool active { get; set; }
public string aggregate_usage { get; set; }
public int amount { get; set; }
public string billing_scheme { get; set; }
public int created { get; set; }
public string currency { get; set; }
public string interval { get; set; }
public int interval_count { get; set; }
public bool livemode { get; set; }
public Metadata2 metadata { get; set; }
public string nickname { get; set; }
public string product { get; set; }
public string tiers { get; set; }
public string tiers_mode { get; set; }
public string transform_usage { get; set; }
public string trial_period_days { get; set; }
public string usage_type { get; set; }
}
public class Datum
{
public string id { get; set; }
public string #string { get; set; }
public int created { get; set; }
public Metadata metadata { get; set; }
public Plan plan { get; set; }
public int quantity { get; set; }
public string subscription { get; set; }
}
public class Items
{
public string #string { get; set; }
public List<Datum> data { get; set; }
public bool has_more { get; set; }
public int total_count { get; set; }
public string url { get; set; }
}
public class Metadata3
{
}
public class Metadata4
{
}
public class Plan2
{
public string id { get; set; }
public string #string { get; set; }
public bool active { get; set; }
public string aggregate_usage { get; set; }
public int amount { get; set; }
public string billing_scheme { get; set; }
public int created { get; set; }
public string currency { get; set; }
public string interval { get; set; }
public int interval_count { get; set; }
public bool livemode { get; set; }
public Metadata4 metadata { get; set; }
public string nickname { get; set; }
public string product { get; set; }
public string tiers { get; set; }
public string tiers_mode { get; set; }
public string transform_usage { get; set; }
public string trial_period_days { get; set; }
public string usage_type { get; set; }
}
public class content
{
public string id { get; set; }
public string #string { get; set; }
public string application_fee_percent { get; set; }
public string billing { get; set; }
public int billing_cycle_anchor { get; set; }
public bool cancel_at_period_end { get; set; }
public string canceled_at { get; set; }
public int created { get; set; }
public int current_period_end { get; set; }
public int current_period_start { get; set; }
public string customer { get; set; }
public string days_until_due { get; set; }
public string default_source { get; set; }
public string discount { get; set; }
public string ended_at { get; set; }
public Items items { get; set; }
public bool livemode { get; set; }
public Metadata3 metadata { get; set; }
public Plan2 plan { get; set; }
public int quantity { get; set; }
public int start { get; set; }
public string status { get; set; }
public string tax_percent { get; set; }
public string trial_end { get; set; }
public string trial_start { get; set; }
}
public class Data
{
public content #object { get; set; }
}
public class Request
{
public string id { get; set; }
public string idempotency_key { get; set; }
}
public class RootObject
{
public string id { get; set; }
public string #string { get; set; }
public string api_version { get; set; }
public int created { get; set; }
public Data data { get; set; }
public bool livemode { get; set; }
public int pending_webhooks { get; set; }
public Request request { get; set; }
public string type { get; set; }
}
use will be like this
var result =JsonConvert.DeserializeObject<RootObject>(data);
Note
There are two way can create model easily.
You can use Web Essentials in Visual Studio, use Edit > Paste special > paste JSON as a class, you can easier to know the relation between Json and model.
If you can't use Web Essentials you can instead of use http://json2csharp.com/ online JSON to Model class.
You can try to use those models to carry your JSON Format.
I have a JSON with multidimensional array. I have no idea how to deserialize it on my c# model. I did a very simple way of deserialization which is not working. I need to know how to deserialize my JSON on more structural way.
This is my json data
{
"Access_point_result": [
{
"msg": {
"ap_eth_mac": {
"addr": "D8C7C8C0C7BE"
},
"ap_name": "1344-1-AL5",
"ap_group": "1344-hq",
"ap_model": "135",
"depl_mode": "DEPLOYMENT_MODE_CAMPUS",
"ap_ip_address": {
"af": "ADDR_FAMILY_INET",
"addr": "10.6.66.67",
"reboots": 1,
"rebootstraps": 2,
"managed_by": {
"af": "ADDR_FAMILY_INET",
"addr": "0.0.0.0"
},
"managed_by_key": "2e302bee0164cc154d1d266d8567ada44d49e77af82f4b5ccb",
"radios": {
"radio_bssid.addr": "D8.C7.C8.46.D8.10"
},
"is_master": true,
"ap_location": {
"ap_eth_mac": "D8C7C8C0C7BE",
"campus_id": "6F9DEC79839D458B9F148D16A46A353E",
"building_id": "83393A922FB249C1929B95393A2AAFDA",
"floor_id": "260BE76B0DD13E7AAF18EB3B47DD7F7B",
"longitude": -122.008,
"latitude": 37.4129,
"ap_x": 22.15,
"ap_y": 99.18
}
},
"ts": 1382046667
}
}
]
}
Below is my C# model
public class WifiDataAruba : BaseModel
{
public string APMACAddr { get; set; }
public string APName { get; set; }
public string APGroup { get; set; }
public string APModel { get; set; }
public string APDeplMode { get; set; }
public string APIPAddr { get; set; }
public int APReboots { get; set; }
public int APRebootStraps { get; set; }
public string APManagedBy { get; set; }
public string APManagedByKey { get; set; }
public string APRadios { get; set; }
public bool APMaster { get; set; }
public string APLocation { get; set; }
public string APMACAddr2 { get; set; }
public string APCampusID { get; set; }
public string APLocationID { get; set; }
public string APBuildingID { get; set; }
public string APFloorID { get; set; }
public double APLongtitude { get; set; }
public double APLatitude { get; set; }
public double X { get; set; }
public double Y { get; set; }
public DateTime ImportTimestamp { get; set; }
}
How can i make the break the deserialization much structural way?
you have to change your model to the following
public class ApEthMac
{
public string addr { get; set; }
}
public class ManagedBy
{
public string af { get; set; }
public string addr { get; set; }
}
public class Radios
{
public string __invalid_name__radio_bssid.addr { get; set; }
}
public class ApLocation
{
public string ap_eth_mac { get; set; }
public string campus_id { get; set; }
public string building_id { get; set; }
public string floor_id { get; set; }
public double longitude { get; set; }
public double latitude { get; set; }
public double ap_x { get; set; }
public double ap_y { get; set; }
}
public class ApIpAddress
{
public string af { get; set; }
public string addr { get; set; }
public int reboots { get; set; }
public int rebootstraps { get; set; }
public ManagedBy managed_by { get; set; }
public string managed_by_key { get; set; }
public Radios radios { get; set; }
public bool is_master { get; set; }
public ApLocation ap_location { get; set; }
}
public class Msg
{
public ApEthMac ap_eth_mac { get; set; }
public string ap_name { get; set; }
public string ap_group { get; set; }
public string ap_model { get; set; }
public string depl_mode { get; set; }
public ApIpAddress ap_ip_address { get; set; }
public int ts { get; set; }
}
public class AccessPointResult
{
public Msg msg { get; set; }
}
public class RootObject
{
public List<AccessPointResult> Access_point_result { get; set; }
}
and your webapi method should look like the following
public void Post(RootObject rootObject)
Note
that you have to add camelcaseconvention in your webapi config if you want to change your c# model to PascalCase
Here how your method should look like in your WebaApiConfig
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
EnableCrossSiteRequests(config);
// Web API routes
config.MapHttpAttributeRoutes();
GlobalConfiguration.Configuration.Formatters.JsonFormatter
.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Model
public class ApEthMac
{
public string addr { get; set; }
}
public class ManagedBy
{
public string af { get; set; }
public string addr { get; set; }
}
public class Radios
{
public string __invalid_name__radio_bssid.addr { get; set; }
}
public class ApLocation
{
public string ap_eth_mac { get; set; }
public string campus_id { get; set; }
public string building_id { get; set; }
public string floor_id { get; set; }
public double longitude { get; set; }
public double latitude { get; set; }
public double ap_x { get; set; }
public double ap_y { get; set; }
}
public class ApIpAddress
{
public string af { get; set; }
public string addr { get; set; }
public int reboots { get; set; }
public int rebootstraps { get; set; }
public ManagedBy managed_by { get; set; }
public string managed_by_key { get; set; }
public Radios radios { get; set; }
public bool is_master { get; set; }
public ApLocation ap_location { get; set; }
}
public class Msg
{
public ApEthMac ap_eth_mac { get; set; }
public string ap_name { get; set; }
public string ap_group { get; set; }
public string ap_model { get; set; }
public string depl_mode { get; set; }
public ApIpAddress ap_ip_address { get; set; }
public int ts { get; set; }
}
public class AccessPointResult
{
public Msg msg { get; set; }
}
public class RootObject
{
public List<AccessPointResult> Access_point_result { get; set; }
}
then DeserializeObject
RootObject rootObject= new RootObject();
rootObject= JsonConvert.DeserializeObject<RootObject>(jsonAgents);
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
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