How can I de-serialize this json with C#? - c#

With C#, I try without success to de-serialize this json content :
{
"code":200,
"message":"OK",
"name":"The name",
"description":"The description",
"tags":{
"0.1.3":{
"date":"2015-03-11",
"author":"SOMEONE",
},
"0.1.2":{
"date":"2015-03-11",
"author":"SOMEONE",
}
}
}
You have noticed, there's a list of "tag" objects, but I have not a table.
Beginning of the target classes :
[DataContract]
public class Project
{
[DataMember]
public int code { get; set; }
[DataMember]
public string message { get; set; }
[DataMember]
public string name { get; set; }
[DataMember]
public string description { get; set; }
[DataMember]
**How can I handle tags entries ?**
}
[DataContract]
public class Tag
{
[DataMember]
public string date { get; set; }
[DataMember]
public string author { get; set; }
}

If you're using JSON.NET, then you can have the following:
[DataContract]
public class Project
{
[DataMember]
public int code { get; set; }
[DataMember]
public string message { get; set; }
[DataMember]
public string name { get; set; }
[DataMember]
public string description { get; set; }
[DataMember]
public Dictionary<string, Tag> tags { get; set; }
}
[DataContract]
public class Tag
{
[DataMember]
public string date { get; set; }
[DataMember]
public string author { get; set; }
}
Which then you would use the following way (assuming responseString contains your JSON):
Project project = JsonConvert.DeserializeObject<Project>(responseString);
foreach (KeyValuePair<string, Tag> tag in project.tags)
{
Debug.WriteLine("Version: {0}", tag.Key);
Debug.WriteLine("Date: {0}", tag.Value.date);
Debug.WriteLine("Author: {0}", tag.Value.author);
}

The JSON input is valid according to RFC 4627 (JSON specfication).
http://www.freeformatter.com/json-validator.html

JSON sturcture is based on Key Value pair. Correct JSON format is like:
{
"object":{
"DataMember1":"String content",
"DataMember2":"String content",
"DataMember3":"String content"
},
"object2":{
"DataMember1":"String content",
"DataMember2":"String content"
}
}
Goto basics
To check your json structure you can validate from click here

Hmm, I was able to deserialize:
Newtonsoft.Json.JsonConvert.DeserializeObject<Project>(json);
However, here is my class definition:
public class Project
{
public string code { get; set; }
public string message { get; set; }
public string name { get; set; }
public string description { get; set; }
public Dictionary<string,Tag> tags { get; set; }
}
public class Tag
{
public string date { get; set; }
public string author { get; set; }
}

Thanks to Arturo Torres Sánchez. To get the "tag" entries, the declaration must be :
[DataContract]
public class Project
{
[DataMember]
public int code { get; set; }
[DataMember]
public string message { get; set; }
[DataMember]
public string name { get; set; }
[DataMember]
public string description { get; set; }
[DataMember]
public Dictionary<string, Tag> tags { get; set; }
}
And the most important, I must modify the default settings and use the new settings when I create the instance of DataContractJsonSerializer.
DataContractJsonSerializerSettings settings =
new DataContractJsonSerializerSettings();
settings.UseSimpleDictionaryFormat = true;
DataContractJsonSerializer serializer =
new DataContractJsonSerializer(typeof(Project), settings);
Project results = (Project)serializer.ReadObject(ms);
Without the settings.UseSimpleDictionaryFormat = true; tag's object count is 0.

Related

JSON DeserializeObject to Model without Key Name

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

Deserializing Json from iTunes store into C# object

I have the following Json returned from iTunes (I have replaced some details for privacy such as username and review content)
{"feed":{"author":{"name":{"label":"iTunes Store"}, "uri":{"label":"http://www.apple.com/uk/itunes/"}}, "entry":[
{"author":{"uri":{"label":"https://itunes.apple.com/gb/reviews/ID"}, "name":{"label":"Username"}, "label":""}, "im:version":{"label":"3.51"}, "im:rating":{"label":"4"}, "id":{"label":"12345"}, "title":{"label":"Review title"}, "content":{"label":"Review contents", "attributes":{"type":"text"}}, "link":{"attributes":{"rel":"related", "href":"https://itunes.apple.com/gb/review?reviewid"}}, "im:voteSum":{"label":"0"}, "im:contentType":{"attributes":{"term":"Application", "label":"Application"}}, "im:voteCount":{"label":"0"}},
// more entries ...
I want to deserialize this into a class. I only need the Review Title, Review contents, and the "im:rating" (which is the number of stars). However, I'm struggling due to the nested Json and the use of keys of how to extract this data. So far I have created a class ready to deserialize, and I have AppStoreData appStoreData = JsonConvert.DeserializeObject<AppStoreData>(stringResult); to deserialize it
public class AppStoreData {
}
My problem is that I don't know what to put inside the class to get the info I need from the Json. I have tried things such as:
public string title {get; set;}
public string content {get; set;}
public string imrating {get; set;}
However this doesn't work. I also think im:rating is an invalid name in C#.
Can anyone please help? Thank you
To get around the issue with im:rating you can use a JsonProperty attribute
[JsonProperty("im:rating")]
public Id ImRating { get; set; }
The issue with converting things like Label to string property is that it's not a string but an object in the input file.
You need something like
[JsonProperty("title")]
public Id Title { get; set; }
where Id is a class
public class Id
{
[JsonProperty("label")]
public string Label { get; set; }
}
Or write a deserializer that converts it to string for you.
I would suggest trying out one of many free code generators like https://app.quicktype.io/?l=csharp or http://json2csharp.com/ to get a headstart and edit everything to your liking afterwards.
I suggest using json2csharp to convert the json to c# model and change the invalid attributes by adding JsonProperty
public class Name
{
public string label { get; set; }
}
public class Uri
{
public string label { get; set; }
}
public class Author
{
public Name name { get; set; }
public Uri uri { get; set; }
}
public class Uri2
{
public string label { get; set; }
}
public class Name2
{
public string label { get; set; }
}
public class Author2
{
public Uri2 uri { get; set; }
public Name2 name { get; set; }
public string label { get; set; }
}
public class ImVersion
{
public string label { get; set; }
}
public class ImRating
{
public string label { get; set; }
}
public class Id
{
public string label { get; set; }
}
public class Title
{
public string label { get; set; }
}
public class Attributes
{
public string type { get; set; }
}
public class Content
{
public string label { get; set; }
public Attributes attributes { get; set; }
}
public class Attributes2
{
public string rel { get; set; }
public string href { get; set; }
}
public class Link
{
public Attributes2 attributes { get; set; }
}
public class ImVoteSum
{
public string label { get; set; }
}
public class Attributes3
{
public string term { get; set; }
public string label { get; set; }
}
public class ImContentType
{
public Attributes3 attributes { get; set; }
}
public class ImVoteCount
{
public string label { get; set; }
}
public class Entry
{
public Author2 author { get; set; }
[JsonProperty(PropertyName = "im:version")]
public ImVersion imversion { get; set; }
[JsonProperty(PropertyName = "im:rating")]
public ImRating imrating { get; set; }
public Id id { get; set; }
public Title title { get; set; }
public Content content { get; set; }
public Link link { get; set; }
[JsonProperty(PropertyName = "im:voteSum")]
public ImVoteSum imvoteSum { get; set; }
[JsonProperty(PropertyName = "im:contentType")]
public ImContentType imcontentType { get; set; }
[JsonProperty(PropertyName = "im:voteCount")]
public ImVoteCount imvoteCount { get; set; }
}
public class Feed
{
public Author author { get; set; }
public List<Entry> entry { get; set; }
}
public class RootObject5
{
public Feed feed { get; set; }
}
Once the model is ready you can use JsonConvert.DeserializeObject to convert the JSON to c# object
using (StreamReader r = new StreamReader(filepath)) {
string json = r.ReadToEnd();
var newEmps = JsonConvert.DeserializeObject<RootObject5>(json);
Console.WriteLine(newEmps.feed.entry[0].imvoteCount.label);
}

c# load Json into inherited class

I have a C# classes and I need to parse JSON into it.
The class has a List<> from another class.
The class structure is like this.
public class OrderFund {
public int OrderID { get; set; }
public int BrokerID { get; set; }
public string SettlementMethod { get; set; }
public List<SettlementSap> SettlementsSap { get; set; }
}
public class SettlementSap {
public string SapMonetaryAccountNo { get; set; }
public string SapMonetaryAccountType { get; set; }
public string SapMonetaryAccountOffice { get; set; }
}
My JSON is like this.
{
"settlementMethod": "SAP",
"BrokerID": 1,
"OrderID": 1,
"Settlements": [
{
"SapMonetaryAccountNo": "400245892464",
"SapMonetaryAccountType": "CA",
"SapMonetaryAccountOffice": "AR"
}
]
}
I load my JSON file like this...
static OrderFund LoadJson(string file) {
string dire = Directory.GetCurrentDirectory();
using (StreamReader r = new StreamReader(dire + "\\" + file)) {
string json = r.ReadToEnd();
OrderFund items = JsonConvert.DeserializeObject<OrderFund>(json);
return items;
}
}
The data load fine into OrderFun Class but OrderFund.SettlementsSap is null.
How can I load Settlements into SettlementsSap?
That's because you have named the field SettlementsSap but your Json field is called Settlements...
You could rename the field in your class;
public class OrderFund
{
public int OrderID { get; set; }
public int BrokerID { get; set; }
public string SettlementMethod { get; set; }
public List<SettlementSap> Settlements { get; set; }
}
or add a [JsonProperty("Settlements")]
attribute to the field like so;
public class OrderFund
{
public int OrderID { get; set; }
public int BrokerID { get; set; }
public string SettlementMethod { get; set; }
[JsonProperty("Settlements")]
public List<SettlementSap> SettlementsSap { get; set; }
}
You just use a function of Visual Studio which convert your json into a model class
Goto: Edit -> Paste special -> Paste JSON as Class
The model class created by this feature will solve your problem
So, visiblely, you must rename SettlementsSap by Settlements
public class OrderFund
{
public string settlementMethod { get; set; }
public int BrokerID { get; set; }
public int OrderID { get; set; }
public Settlement[] Settlements { get; set; }
}
public class Settlement
{
public string SapMonetaryAccountNo { get; set; }
public string SapMonetaryAccountType { get; set; }
public string SapMonetaryAccountOffice { get; set; }
}
The problem is with the naming. In the JSON, the name is Settlements. But in the class definition of OrderFund it is named as SettlementsSap

How to deserialize json into collection of Objects

I have the following JSON (I can't change the incoming JSON as it is from a 3rd party system):
{
"id": 23,
"userName":"test#test.com",
"tags":
{
"Employee ID":
{
"name":"Employee ID",
"value":"123456789"
},
"Job Family":
{
"name": "Job Family",
"value": "Accounting and Finance"
}
}
}
First, I tried to deserialize using this class structure:
public class User
{
[JsonProperty("id")]
public int ID { get; set; }
[JsonProperty("username")]
public string Email { get; set; }
[JsonProperty("tags")]
public TagsJson Tags { get; set; }
}
public class TagsJson
{
[JsonProperty("tags")]
public List<Tag> Tags { get; set; }
}
public class Tag
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
}
In using Newtonsoft's JsonConvert.DeserializeObject(json);, the User.Tags property is always empty. This is obviously because there are no "Tags" under the "Tags" attribute.
Yet, if I change the User class as follows...
public class User
{
[JsonProperty("id")]
public int ID { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("tags")]
public List<Tag> Tags { get; set; }
// I even tried Tag[] instead of List<Tag> here
}
...I get the following error:
Additional information: Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type
'System.Collections.Generic.List`1[Tag]' because the type requires
a JSON array (e.g. [1,2,3]) to deserialize correctly.
Any suggestions on creating the User class to allow it to deserialize correctly would be greatly appreciated.
EDIT
So this may or may not be the best answer, but it works. The tags coming in will be one of a dozen different names. So I created a Tags class with a property for each of the 12 possibilites. Since none are required, any of them that do appear will get populated. Here's my adjusted User, Tags (formerly TagsJson) and Tag classes below - but I'm definitely interested in a better solution.
public class User
{
[JsonProperty("id")]
public int ID { get; set; }
[JsonProperty("username")]
public string Email { get; set; }
[JsonProperty("tags")]
public Tags AllTags { get; set; }
}
public class Tags
{
[JsonProperty("Employee ID")]
public Tag EmployeeID { get; set; }
[JsonProperty("Job Family")]
public Tag JobFamily { get; set; }
// ... and 10 more properties for additional tags that may appear but are not required
}
public class Tag
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
}
The suggested answer of this question does not work in my case because the JSON is not an array or a collection but a list of unique attribute names with a name/value pairing.
Well using the Visual Studio paste Json as classes yields...
public class Rootobject
{
public int id { get; set; }
public string userName { get; set; }
public Tags tags { get; set; }
}
public class Tags
{
[JsonProperty(PropertyName = "Employee ID")]
public EmployeeID EmployeeID { get; set; }
[JsonProperty(PropertyName = "Job Family")]
public JobFamily JobFamily { get; set; }
}
public class EmployeeID
{
public string name { get; set; }
public string value { get; set; }
}
public class JobFamily
{
public string name { get; set; }
public string value { get; set; }
}
I had to add in the JsonProperty attributes myself. However I think a better solution would be...
public class Rootobject2
{
public int id { get; set; }
public string userName { get; set; }
public IDictionary<string, NameValuePair> tags { get; set; }
}
public class NameValuePair
{
public string name { get; set; }
public string value { get; set; }
}
Although the paste Json as classes was a good starting point to easily copy and paste the code into the favoured solution.
Some test code...
string json = Resource1.String1;
Rootobject test = JsonConvert.DeserializeObject<Rootobject>(json);
Rootobject2 test2 = JsonConvert.DeserializeObject<Rootobject2>(json);
Not sure your JSON is correct but why is there space in your property name Employee ID or Job Family. Fix those in Tags class and we are good to go.
public class EmployeeID
{
public string name { get; set; }
public string value { get; set; }
}
public class JobFamily
{
public string name { get; set; }
public string value { get; set; }
}
public class Tags
{
public EmployeeID __invalid_name__Employee ID { get; set; }
public JobFamily __invalid_name__Job Family { get; set; }
}
public class User
{
public int id { get; set; }
public string userName { get; set; }
public Tags tags { get; set; }
}
This is what i got from json2csharp.com
Your JSON shows that your tags object is an Object - not an Array. You cannot deserialize an Object into a C# List because they are different structures.
If the keys in tags are dynamic/changing, then perhaps try
[JsonProperty("tags")]
Dictionary<string, string> Tags { get; set; }
Edit
It appears that your JSON is not well-formed; if you aren't able to modify it, you might have to use a custom JsonConverter.

JSON deserializing to C# types

I have got following JSON that should be deserialized to C# class:
{"status":"error","messages":[{"level":"error","key":"InvalidTokenError","dsc":"Invalid
token"}]}
So I have a questions what is the kind of type should be
[{"level":"error","key":"InvalidTokenError","dsc":"Invalid token"}]
?
Is this array, list or class?
You can use json2csharp.com to get the types of the JSON.
JSON:
{"status":"error","messages":[{"level":"error","key":"InvalidTokenError","dsc":"Invalid token"}]}
Here is the classes generated for your JSON:
public class Message
{
public string level { get; set; }
public string key { get; set; }
public string dsc { get; set; }
}
public class RootObject
{
public string status { get; set; }
public List<Message> messages { get; set; }
}
for JSON:
[{"level":"error","key":"InvalidTokenError","dsc":"Invalid token"}]
Type:
public class Message
{
public string level { get; set; }
public string key { get; set; }
public string dsc { get; set; }
}
You can use this site
public class Message
{
public string level { get; set; }
public string key { get; set; }
public string dsc { get; set; }
}
public class RootObject
{
public string status { get; set; }
public List<Message> messages { get; set; }
}

Categories