I have a web service which I get a complex Json object, everything is fine, but there is a class in this object that changes its name in each response according on Item name, this prevents the normal deserialization process
public class Threads
{
public object threads { get; set; }
public object error { get; set; }
public Async async { get; set; }
public Products products { get; set; } => Products Class
}
public class Products
{
//public DR7614060 dr7614060 { get; set; }
// I try to Deserialize the class as Dictionary but nothing happend
Dictionary<string, DR7614060> Pairs { get ; set; }
}
public class DR7614060
{
public string id { get; set; }
public string threadId { get; set; }
public string productId { get; set; }
public bool mainColor { get; set; }
public Productrollup productRollup { get; set; }
}
Json :
https://github.com/Kremed/ContenPageFlowDirection/blob/master/Json.json
I was able to get this configuration to work:
public class Threads
{
[JsonProperty("threads")]
public object ThreadsThreads { get; set; }
[JsonProperty("error")]
public object Error { get; set; }
[JsonProperty("async")]
public ThreadsAsync Async { get; set; }
[JsonProperty("products")]
public Dictionary<string, StupidClassName> Products { get; set; }
}
I think you were on the right track, you just need to move the dictionary up one level to allow for the key value pair to be based on the name of the class. So that leaves the DR7614060 definition. Just give it a proper class name to use for deserialization. Now your Products dictionary will have key = 'given class name' value = 'deserialized object with defined class name'
public partial class StupidClassName // instead of DMxxxxxx
{
[JsonProperty("id")]
public Guid Id { get; set; }
[JsonProperty("threadId")]
public Guid ThreadId { get; set; }
[JsonProperty("productId")]
[JsonConverter(typeof(ParseStringConverter))]
public long ProductId { get; set; }
[JsonProperty("mainColor")]
public bool MainColor { get; set; }
[JsonProperty("productRollup")]
public ProductRollup ProductRollup { get; set; }
// .... more props etc.
}
From the Json you posted I got:
Related
I currently have JSON coming in as follows:
{"36879":[{"min_qty":1,"discount_type":"%","csp_price":10}],"57950":[{"min_qty":1,"discount_type":"flat","csp_price":650}]}
This contains a list of the following records
ProductId
MinQty
DiscountType
Price
I need to deserialize this into the following model:
public class CustomerSpecificPricing
{
string productId { get; set; }
public virtual List<CustomerSpecificPricingDetail> CustomerSpecificPricingDetails { get; set; }
}
public class CustomerSpecificPricingDetail
{
public string min_qty { get; set; }
public string discount_type { get; set; }
public string csp_price { get; set; }
}
The problem is that the "productId" of each record is missing the key name.
If I run my JSON through J2C, I get the following:
public class 36879 {
public int min_qty { get; set; }
public string discount_type { get; set; }
public int csp_price { get; set; }
}
public class 57950 {
public int min_qty { get; set; }
public string discount_type { get; set; }
public int csp_price { get; set; }
}
public class Root {
public List<_36879> _36879 { get; set; }
public List<_57950> _57950 { get; set; }
}
Which is obviously incorrect.
How would I deserialize my object correctly?
You would need to deserialize it into a dictionary first and then map it into the format you require after. Something like this should work:
var dict = JsonConvert.DeserializeObject<Dictionary<string, IEnumerable<CustomerSpecificPricingDetail>>>();
var result = dict.Select(kvp => new CustomerSpecificPricing { ProductId = Int32.Parse(kvp.Key), CustomerSpecificPricingDetails = kvp.Value });
Id also recommend you follow the conventional standards of naming. In this case properties in classes should be PascalCase,
e.g. your classes now become:
public class CustomerSpecificPricing
{
[JsonProperty("productId ")]
public string ProductId { get; set; }
public virtual List<CustomerSpecificPricingDetail> CustomerSpecificPricingDetails { get; set; }
}
and
public class CustomerSpecificPricingDetail
{
[JsonProperty("min_qty")]
public string MinQty { get; set; }
[JsonProperty("discount_type ")]
public string DiscountType { get; set; }
[JsonProperty("csp_price ")]
public string CspPrice { get; set; }
}
public class 2500113075262000 {
public string pair { get; set; }
public string type { get; set; }
public double amount { get; set; }
public int rate { get; set; }
public string timestamp_created { get; set; }
public int status { get; set; }
}
public class Return {
public 2500113075262000 2500113075262000 { get; set; }
}
public class Root {
public int success { get; set; }
public Return #return { get; set; }
}
class 2500113075262000 is constantly changing, this is the order ID, like deserialize
{"success":1,"return":{"2500113075262000":{"pair":"eth_rur","type":"sell","amount":0.00110569,"rate":46100,"timestamp_created":"1608918997","status":0}}}
It looks like it's only the key - presumably the order ID - which is changing. I would suggest removing your Return class entirely, and changing your Root class to have a Dictionary<string, Order>. I'd also suggest writing your classes with idiomatic .NET property names, and using JsonPropertyAttribute to specify the representation in the JSON. So it would be something like this:
public class Order
{
[JsonProperty("pair")]
public string Pair { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
// etc, other properties
}
public class Root
{
[JsonProperty("success")]
public int Success { get; set; }
[JsonProperty("return")]
public Dictionary<string, Order> Returns { get; set; }
}
I am getting the below JSON in response from a REST API.
{
"data":{
"id":123,
"zoneid":"mydomain.com",
"parent_id":null,
"name":"jaz",
"content":"172.1 6.15.235",
"ttl":60,
"priority":null,
"type":"A",
"regions":[
"global"
],
"system_record":false,
"created_at":"2017-09-28T12:12:17Z",
"updated_at":"2017-09-28T12:12:17Z"
}
}
and trying to resolve using below code but that doesn't result in a correctly deserialized type.
var model = JsonConvert.DeserializeObject<ResponseModel>(response);
below is a class according the field I received in JSON response.
public class ResponseModel
{
public int id { get; set; }
public string zone_id { get; set; }
public int parent_id { get; set; }
public string name { get; set; }
public string content { get; set; }
public int ttl { get; set; }
public int priority { get; set; }
public string type { get; set; }
public string[] regions { get; set; }
public bool system_record { get; set; }
public DateTime created_at { get; set; }
public DateTime updated_at { get; set; }
}
What is missing?
You're missing a wrapper class.
public class Wrapper
{
public ResponseModel data {get;set}
}
and then do:
var model = JsonConvert.DeserializeObject<Wrapper>(response).data;
to get the instance of your ResponseModel out the data property.
You can deduct this from your json:
{ "data":
{ "id":123, /*rest omitted */ }
}
The type that will receive this JSON needs to have a property named data. The suggested Wrapper class acts as that type.
According to json2csharp website, your model seems to be incorrect. Try this one :
public class ResponseModel
{
public int id { get; set; }
public string zoneid { get; set; }
public object parent_id { get; set; }
public string name { get; set; }
public string content { get; set; }
public int ttl { get; set; }
public object priority { get; set; }
public string type { get; set; }
public List<string> regions { get; set; }
public bool system_record { get; set; }
public DateTime created_at { get; set; }
public DateTime updated_at { get; set; }
}
public class RootObject
{
public ResponseModel data { get; set; }
}
Here a cool trick you can do in Visual Studio 2015-2017 where it generates the the correct class if you just copy the JSON (ctrl + c).
You need to create a new class in visual studio and once inside the class go to Edit menu -> Paste special -> paste JSON As Classes.
Steps to generate json class
This will generate the C# object for that json for you and save you all the hassle :)
Your model does not match your response - it matches the data property. Simply wrap another object round it
public class ResponseData
{
public ResponseModel Data {get; set; {
}
and then
var model = JsonConvert.DeserializeObject<ResponseData>(response);
I've generated a C# class from sample JSON output using the Graph Explorer with Contacts (as per below). However, when I pass the serialized object (using JsonConvert.SerializeObject(myclass)) with null values for string array properties to a POST operation to create the Contact I get the following error in the response:
A null value was found for the property named 'BusinessPhones', which
has the expected type 'Collection(Edm.String)[Nullable=False]'. The
expected type 'Collection(Edm.String)[Nullable=False]' does not allow
null values.
(for reference, these are the supported Contact properties: https://msdn.microsoft.com/en-us/office/office365/api/complex-types-for-mail-contacts-calendar#contact)
Here's an example of the raw JSON:
{"AssistantName":null,"Birthday":null,"BusinessAddress":null,"BusinessPhones":null,"Categories":null,"Children":null,"CompanyName":"Fun Toys and Bikes","Department":null,"DisplayName":"Mr. Robert E. Ahlering","EmailAddresses":[{"Address":"robert#funtoys.com","Name":"Robert E. Ahlering (robert#funtoys.com)"}],"FileAs":null,"Generation":null,"GivenName":"Robert","HomeAddress":null,"Initials":null,"JobTitle":"Owner","Manager":null,"MiddleName":null,"MobilePhone1":null,"NickName":null,"OfficeLocation":null,"OtherAddress":null,"PersonalNotes":null,"Profession":null,"SpouseName":null,"Surname":"Ahlering","Title":null,"YomiCompanyName":null,"YomiGivenName":null,"YomiSurname":null}
I believe the correct formatting for a null BusinessPhones value (to pick one of the string arrays) should be "BusinessPhones":[], and not "BusinessPhones:null".
So how do I implement string array/collection properties in the class to accommodate this?
public partial class OutlookContact
{
public partial class Businessaddress
{
public object City { get; set; }
public object CountryOrRegion { get; set; }
public object PostalCode { get; set; }
public object State { get; set; }
public object Street { get; set; }
}
public partial class Emailaddress
{
public string Address { get; set; }
public string Name { get; set; }
}
public partial class Homeaddress
{
public string City { get; set; }
public object CountryOrRegion { get; set; }
public string PostalCode { get; set; }
public string State { get; set; }
public string Street { get; set; }
}
public partial class Otheraddress
{
public object City { get; set; }
public object CountryOrRegion { get; set; }
public object PostalCode { get; set; }
public object State { get; set; }
public object Street { get; set; }
}
public partial class Rootobject
{
public object AssistantName { get; set; }
public DateTime? Birthday { get; set; }
public Businessaddress BusinessAddress { get; set; }
public string[] BusinessPhones { get; set; }
public object[] Categories { get; set; }
public object[] Children { get; set; }
public object CompanyName { get; set; }
public string Department { get; set; }
public string DisplayName { get; set; }
public Emailaddress[] EmailAddresses { get; set; }
public string FileAs { get; set; }
public object Generation { get; set; }
public string GivenName { get; set; }
public Homeaddress HomeAddress { get; set; }
public object Initials { get; set; }
public string JobTitle { get; set; }
public object Manager { get; set; }
public object MiddleName { get; set; }
public object MobilePhone1 { get; set; }
public object NickName { get; set; }
public string OfficeLocation { get; set; }
public Otheraddress OtherAddress { get; set; }
public object PersonalNotes { get; set; }
public object Profession { get; set; }
public object SpouseName { get; set; }
public string Surname { get; set; }
public object Title { get; set; }
public object YomiCompanyName { get; set; }
public object YomiGivenName { get; set; }
public object YomiSurname { get; set; }
}
}
You need to initialize BusinessPhones property to an empty array in the constructor of RootObject class as following.
public partial class RootObject
{
public RootObject()
{
this.BusinessPhones = new string[0];
}
// rest of the class...
}
And if that's not possible, you need to make sure that the BusinessPgones is initialized to empty array before you serialize it to JSON string.
var rootObject = new RootObject();
rootObject.BusinessPhones = new string[];
// set other properties of rootObject
//Serialize rootObject to JSON
// Call rest API.
This should resolve your issue.
From the error null collection is not allowed. You should be able to use any empty collection instead:
"BusinessPhones": []
Here is an example snippet of the json data that the API returns:
{
"realm":{"name":"Molten Core","slug":"molten-core"},
"auctions":{"auctions":[
{"auc":1880591075,"item":109128,"owner":"Leagra","ownerRealm":"Azjol-Nerub","bid":858600,"buyout":900000,"quantity":100,"timeLeft":"VERY_LONG","rand":0,"seed":0,"context":0},
{"auc":1879726534,"item":43115,"owner":"Nêwt","ownerRealm":"Azjol-Nerub","bid":5120000,"buyout":5120000,"quantity":16,"timeLeft":"VERY_LONG","rand":0,"seed":835268864,"context":0}]}
}
(Though obviously with real data there's thousands of auctions.)
I'm looking to deserialise this, ignoring the realm data and just putting the auctions into a nice clean List<WowAuction> object, with WowAuction being:
public class WowAuction
{
public long auc { get; set; }
public long item { get; set; }
public long bid { get; set; }
public long buyout { get; set; }
}
I'm having trouble wrapping my head around how I would do this, the json the API returns seems rather messy to me (though admittedly I haven't worked with json before).
As far as I can tell, there's a collection called "auctions", inside of that is a single field also called "auctions" which is a table, that table then contains rows of auction data. How would I deserialise this?
There are many ways you could do that but the simple way is to create a domain object with the same structure as your JSON:
public class WoWAuctionResponse {
public WoWRealmInfo Realm {get; set;}
public WoWAuctionsBody Auctions {get; set;}
}
public class WoWAuctionsBody {
public List<WoWAuction> Auctions {get; set;}
}
// ...
JsonConvert.DeserializeObject<WoWAuctionResponse>(json);
To extend #slvnperron's answer.
First, build your classes. I recommend to use a tool like json2csharp.
public class Realm
{
public string name { get; set; }
public string slug { get; set; }
}
public class Auction
{
public int auc { get; set; }
public int item { get; set; }
public string owner { get; set; }
public string ownerRealm { get; set; }
public int bid { get; set; }
public int buyout { get; set; }
public int quantity { get; set; }
public string timeLeft { get; set; }
public int rand { get; set; }
public int seed { get; set; }
public int context { get; set; }
}
public class Auctions
{
public List<Auction> auctions { get; set; }
}
public class RootObject
{
public Realm realm { get; set; }
public Auctions auctions { get; set; }
}
Second, parse your json. i recommend to use a tool like Json.net. You can install it with nuget.
public static void Main()
{
string json = #"{here your json}";
RootObject m = JsonConvert.DeserializeObject<RootObject>(json);
Console.WriteLine(m.realm.name.Trim());
}
here our output will be :
Molten Core
Working example on dotnetfiddle.
Have your domain model this way and deserialize your data.
internal class WowAuction
{
[JsonProperty("realm")]
public Realm Realm { get; set; }
[JsonProperty("auctions")]
public Auctions Auctions { get; set; }
}
internal class Realm
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("slug")]
public string Slug { get; set; }
}
internal class Auctions
{
[JsonProperty("auctions")]
public Auction[] Auctions { get; set; }
}
internal class Auction
{
[JsonProperty("auc")]
public int Auc { get; set; }
[JsonProperty("item")]
public int Item { get; set; }
[JsonProperty("owner")]
public string Owner { get; set; }
[JsonProperty("ownerRealm")]
public string OwnerRealm { get; set; }
[JsonProperty("bid")]
public int Bid { get; set; }
[JsonProperty("buyout")]
public int Buyout { get; set; }
[JsonProperty("quantity")]
public int Quantity { get; set; }
[JsonProperty("timeLeft")]
public string TimeLeft { get; set; }
[JsonProperty("rand")]
public int Rand { get; set; }
[JsonProperty("seed")]
public int Seed { get; set; }
[JsonProperty("context")]
public int Context { get; set; }
}
Later you can have following statement to deserialize your data
JsonConvert.DeserializeObject<WowAuction>(data);
Things have changed a bit since this question was originally asked. The World of Warcraft APIs now include Game Data and Profile APIs. As the other answers here describe, you can create model classes and use Json.NET or a similar library to handle the deserialization. There are also NuGet packages like the Argent Pony Warcraft Client or the BattleMuffin Blizzard API Client that have already defined model classes and handle the deserialization for you.
An example with the ArgentPonyWarcraftClient NuGet package follows. It displays a subset of the information available for each auction.
string clientId = "CLIENT-ID-GOES-HERE";
string clientSecret = "CLIENT-SECRET-GOES-HERE";
int connectedRealmId = 1146;
IAuctionHouseApi warcraftClient = new WarcraftClient(
clientId: clientId,
clientSecret: clientSecret,
region: Region.US,
locale: Locale.en_US);
RequestResult<AuctionsIndex> result = await warcraftClient.GetAuctionsAsync(connectedRealmId, "dynamic-us");
if (result.Success)
{
AuctionsIndex auctions = result.Value;
foreach(Auction auction in auctions.Auctions)
{
Console.WriteLine($"{auction.Id}: Item ID: {auction.Item.Id} Quantity: {auction.Quantity}");
}
}