I'm reading some Json from an api which I don't own, and therefore, I can't change the response. When I'm deserializing the Json into C# objects using Newtonsoft, I'm running into a problem with the 'ChangedAttributes' field. When creating these classes, Visual Studio wants to create a class for 'Sex', and one for 'MaritalStatus', but they aren't being populated. Furthermore, the list of ChangedAttributes can be any number of hundreds of different possibilities. So, I'd like to deserialize those attributes into a generic type class, say, something like:
public class Attribute
{
public string Name {get;set;}
public string Old {get;set;}
public string New {get;set;}
}
Can someone tell me how I might accomplish that using Newtonsoft? Here's a sample of the Json that I'm trying to parse:
{
"Context" : [ {
"PersonName" : "Smith, Bob",
"PersonNumber" : "001246",
"PrimaryPhoneNumber" : "",
"PersonId" : "300000009560451",
"WorkerType" : "EMP",
"PeriodType" : "E",
"DMLOperation" : "UPDATE",
"EffectiveStartDate" : "2004-08-27",
"EffectiveDate" : "2004-08-27"
} ],
"Changed Attributes" : [ {
"Sex" : {
"old" : null,
"new" : "M"
}
}, {
"MaritalStatus" : {
"old" : null,
"new" : "S"
}
} ]
}
Here are the C# classes that VS generated for me:
public class AtomFeed_Empupdate
{
public AtomFeed_Empupdate_Context[] Context { get; set; }
public AtomFeed_Empupdate_ChangedAttribute[] ChangedAttributes { get; set; }
}
public class AtomFeed_Empupdate_Context
{
public string PersonName { get; set; }
public string PersonNumber { get; set; }
public string WorkEmail { get; set; }
public string PrimaryPhoneNumber { get; set; }
public string PersonId { get; set; }
public string WorkerType { get; set; }
public string PeriodType { get; set; }
public string DMLOperation { get; set; }
public string EffectiveStartDate { get; set; }
public string EffectiveDate { get; set; }
}
public class AtomFeed_Empupdate_ChangedAttribute
{
public AtomFeed_Empupdate_Sex Sex { get; set; }
public AtomFeed_Empupdate_Maritalstatus MaritalStatus { get; set; }
}
public class AtomFeed_Empupdate_Sex
{
public string old { get; set; }
public string _new { get; set; }
}
public class AtomFeed_Empupdate_Maritalstatus
{
public string old { get; set; }
public string _new { get; set; }
}
And here is how I am deserializing the Json:
AtomFeed_Empupdate eu = Newtonsoft.Json.JsonConvert.DeserializeObject<AtomFeed_Empupdate>(json);
Thanks for your help!
You may change Attribute class a little bit and decorate it with JsonProperty attribute with proper names
public class Attribute
{
[JsonProperty("old")]
public string Old { get; set; }
[JsonProperty("new")]
public string New { get; set; }
}
And use Dictionary<string, Attribute>[] (since you have an array of key-value pairs) for Changed Attributes JSON token
public class AtomFeed_Empupdate
{
public AtomFeed_Empupdate_Context[] Context { get; set; }
[JsonProperty("Changed Attributes")]
public Dictionary<string, Attribute>[] ChangedAttributes { get; set; }
}
Related
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
I've this json:
{
"page": "36",
"bookmaker_urls": {
"13": [{
"link": "http://www.bet365.com/home/?affiliate=365_179024",
"name": "Bet 365"
}]
},
"block_service_id": "competition_summary_block_competitionmatchessummary",
"round_id": "36003",
"outgroup": "",
"view": "1",
"competition_id": "13"
}
I've inserted this on this tool: http://json2csharp.com/
this will return:
public class __invalid_type__13
{
public string link { get; set; }
public string name { get; set; }
}
public class BookmakerUrls
{
public List<__invalid_type__13> __invalid_name__13 { get; set; }
}
public class RootObject
{
public int page { get; set; }
public BookmakerUrls bookmaker_urls { get; set; }
public string block_service_id { get; set; }
public int round_id { get; set; }
public bool outgroup { get; set; }
public int view { get; set; }
public int competition_id { get; set; }
}
why there is an invalid type?
13 is not a valid property name in .NET, and the tool you're using seems to try to map each JSON property to .NET Class property.
What you probably want is bookmaker_urls to be a dictionary:
public class BookmakerUrl
{
public string link { get; set; }
public string name { get; set; }
}
public class RootObject
{
public int page { get; set; }
public Dictionary<string, List<BookmakerUrl>> bookmaker_urls { get; set; }
public string block_service_id { get; set; }
public int round_id { get; set; }
public bool outgroup { get; set; }
public int view { get; set; }
public int competition_id { get; set; }
}
The generator generates the name of properties and types from the name of properties in the Json.
There is a property "13" in the Json. A name starting with a digit would not be a valid name in c#.
So, the generator just adds the prefix "invalid_name" or "invalid_type" to the generated names. This does not mean that there was any problem or that you cannot use the generated code.
I have a JSON returning from web like this
{
"data": {
"normal_customer": {
"0": {
"id": 1,
"name": "ALPHY"
}
},
"1": {
"id": 2,
"name": "STEVEN"
}
},
"luxury_customer": {
"3": {
"id": 8,
"name": "DEV"
}
}
}
}
I have created c# classes
public class StandardCustomers
{
public List<CustomersDetails> Customers_Details { get; set; }
}
public class CustomersDetails
{
[JsonProperty("id")]
public int id { get; set; }
[JsonProperty("name")]
public string name { get; set; }
public class LuxuryCustomers
{
public List<CustomersDetails> Customers_Details { get; set; }
}
public class Data
{
public StandardCustomers standard_Customers { get; set; }
public LuxuryCustomers luxury_Customers { get; set; }
}
public class RootObject
{
public Data data { get; set; }
}
}
When I use deserialize the response from the website using below c# code
var result1 = JsonConvert.DeserializeObject<Data>(response);
but result1.luxury_customers contains customerdetails which is null.
As suggested by #hellostone, I have modified to rootdata, then also
result1.luxury_customers contains customerdetails is null.
Any idea how to deserialize to c# class
When we pasted Json to visual studio, it generated classes as below
public class Rootobject
{
public Data data { get; set; }
}
public class Data
{
public Standard_Customers standard_Customers { get; set; }
public Luxury_Customers luxury_Customers { get; set; }
}
public class Standard_Customers
{
public _0 _0 { get; set; }
public _1 _1 { get; set; }
public _2 _2 { get; set; }
public _4 _4 { get; set; }
public _5 _5 { get; set; }
}
public class _0
{
public int id { get; set; }
public string name { get; set; }
}
individual classes are generated in standard customers , can we use list for this
I guess the problem is that index in luxury_customers starting not from zero. Try to use Dictionary<string,CustomersDetails> in LuxuryCustomers instead List<CustomersDetails>.
I've managed to deserialize Json with this classes:
public class CustomersDetails
{
[JsonProperty("id")]
public int id { get; set; }
[JsonProperty("name")]
public string name { get; set; }
}
public class Data
{
public Dictionary<string, CustomersDetails> normal_customer { get; set; }
public Dictionary<string,CustomersDetails> luxury_customer { get; set; }
}
public class RootObject
{
public Data data { get; set; }
}
Deserialization code:
var result = JsonConvert.DeserializeObject<RootObject>(text);
P.S. I've remove one closing bracket after "ALPHY" element, to make Json valid, I hope it was typo and you're getting valid Json.
Your json string doesn't match with your defined classes. Your Json string should look like this if you want to preserve your class structure:
{
"data":{
"standard_Customers":{
"Customers_Details":[
{
"id":1,
"name":"ALPHY"
},
{
"id":2,
"name":"STEVEN"
}
]
},
"luxury_Customers":{
"Customers_Details":[
{
"id":8,
"name":"DEV"
}
]
}
}
}
Pay attention to the square brackets at the "Customers_Details" attribute.
Then the:
var result1 = JsonConvert.DeserializeObject<RootObject>(response);
call, will give you the right object back and it shouldn't be null, when using your class structure:
public class StandardCustomers
{
public List<CustomersDetails> Customers_Details { get; set; }
}
public class CustomersDetails
{
[JsonProperty("id")]
public int id { get; set; }
[JsonProperty("name")]
public string name { get; set; }
}
public class LuxuryCustomers
{
public List<CustomersDetails> Customers_Details { get; set; }
}
public class Data
{
public StandardCustomers standard_Customers { get; set; }
public LuxuryCustomers luxury_Customers { get; set; }
}
public class RootObject
{
public Data data { get; set; }
}
After making an api call, the example below shows what a typical response would be.
{
"code":"success",
"message":"Data retrieved for email",
"data":{
"attributes":{
"EMAIL":"example#example.net",
"NAME" : "Name",
"SURNAME" : "surname"
},
"blacklisted":1,
"email":"example#example.net",
"entered":"2014-01-15",
"listid":[8],
"message_sent":[{
"camp_id" : 2,
"event_time" : "2013-12-18"
},
{ "camp_id" : 8,
"event_time" : "2014-01-03"
},
{ "camp_id" : 11,
"event_time" : "2014-01-07"
}],
"hard_bounces":[{
"camp_id" : 11,
"event_time" : "2014-01-07"
}],
"soft_bounces":[],
"spam":[{
"camp_id" : 2,
"event_time" : "2014-01-09"
}],
"unsubscription":{
"user_unsubscribe":[
{
"event_time":"2014-02-06",
"camp_id":2,
"ip":"1.2.3.4"
},
{
"event_time":"2014-03-06",
"camp_id":8,
"ip":"1.2.3.4"
}
],
"admin_unsubscribe":[
{
"event_time":"2014-04-06",
"ip":"5.6.7.8"
},
{
"event_time":"2014-04-16",
"ip":"5.6.7.8"
}
]
},
"opened":[{
"camp_id" : 8,
"event_time" : "2014-01-03",
"ip" : "1.2.3.4"
}],
"clicks":[],
"transactional_attributes":[
{
"ORDER_DATE":"2015-07-01",
"ORDER_PRICE":100000,
"ORDER_ID":"1"
},
{
"ORDER_DATE":"2015-07-05",
"ORDER_PRICE":500000,
"ORDER_ID":"2"
}
],
"blacklisted_sms":1
}
}
What I need to do is to be able to read / find and attribute name and its corresponding value. I also need to know the value of blacklisted.
I don't know how to interpret the output given to easily find and read attributes and their values and also get the value of blacklisted.
Maybe if I can get it into an array, I can cycle through the array to find the value pair I am looking for? Or maybe I am overthinking it and their is an easier way.
Please note: This example only shows 3 attribute:value pairs. other calls may output more than three attribute:value pairs.
The simplest way is: You are getting the response in the JSON format and you just need it to be seralized with the use of classes and Json.NET
public class Rootobject
{
public string code { get; set; }
public string message { get; set; }
public Data data { get; set; }
}
public class Data
{
public Attributes attributes { get; set; }
public int blacklisted { get; set; }
public string email { get; set; }
public string entered { get; set; }
public int[] listid { get; set; }
public Message_Sent[] message_sent { get; set; }
public Hard_Bounces[] hard_bounces { get; set; }
public object[] soft_bounces { get; set; }
public Spam[] spam { get; set; }
public Unsubscription unsubscription { get; set; }
public Opened[] opened { get; set; }
public object[] clicks { get; set; }
public Transactional_Attributes[] transactional_attributes { get; set; }
public int blacklisted_sms { get; set; }
}
public class Attributes
{
public string EMAIL { get; set; }
public string NAME { get; set; }
public string SURNAME { get; set; }
}
public class Unsubscription
{
public User_Unsubscribe[] user_unsubscribe { get; set; }
public Admin_Unsubscribe[] admin_unsubscribe { get; set; }
}
public class User_Unsubscribe
{
public string event_time { get; set; }
public int camp_id { get; set; }
public string ip { get; set; }
}
public class Admin_Unsubscribe
{
public string event_time { get; set; }
public string ip { get; set; }
}
public class Message_Sent
{
public int camp_id { get; set; }
public string event_time { get; set; }
}
public class Hard_Bounces
{
public int camp_id { get; set; }
public string event_time { get; set; }
}
public class Spam
{
public int camp_id { get; set; }
public string event_time { get; set; }
}
public class Opened
{
public int camp_id { get; set; }
public string event_time { get; set; }
public string ip { get; set; }
}
public class Transactional_Attributes
{
public string ORDER_DATE { get; set; }
public int ORDER_PRICE { get; set; }
public string ORDER_ID { get; set; }
}
Use Newtonsoft.Json library. One of the most powerful library.Parse your JSON to strongly typed C# object using json2csharp.com then just deserialize the string.
var model= JsonConvert.DeserializeObject<Classname>(result);
You'll need JSON.Net. Pasrse your JSON to strongly typed C# object using json2csharp.com then just deserialize the string using JsonConvert.Deserialize<RootObject>().
One way would be to:
a) Copy your JSON to Clipboard (CTRL+C)
b) On a Visual Studio class, click on EDIT-> Paste Special -> Paste JSON as classes. This will create the classes equivalent of your JSON for you. Your main object would be named as "Rootobject" and you can change this to whatever name you want.
c) Add System.Web.Extensions to your references
d) You can convert your JSON to class like so:
JavaScriptSerializer serializer = new JavaScriptSerializer();
Rootobject rootObject = serializer.Deserialize<Rootobject>(JsonString);
Where JsonString is your API output.
I have this specific JSON response that I am trying to deserialize without success. I am hoping someone can help me.
Here is the JSON response I get:
{
"num_locations": 1,
"locations": {
"98765": {
"street1": "123 Fake Street",
"street2": "",
"city": "Lawrence",
"state": "Kansas",
"postal_code": "66044",
"s_status": "20",
"system_state": "Off"
}
}
}
I used json2csharp http://json2csharp.com and got these recommended classes:
public class __invalid_type__98765
{
public string street1 { get; set; }
public string street2 { get; set; }
public string city { get; set; }
public string state { get; set; }
public string postal_code { get; set; }
public string s_status { get; set; }
public string system_state { get; set; }
}
public class Locations
{
public __invalid_type__98765 __invalid_name__98765 { get; set; }
}
public class RootObject
{
public int num_locations { get; set; }
public Locations locations { get; set; }
}
But when I try to use it in my code:
var locationResponse = JsonConvert.DeserializeObject<RootObject>(response.Content);
What I get is (Watch):
locationResponse : {RestSharpConsoleApplication.Program.RootObject} : RestSharpConsoleApplication.Program.RootObject
locations : {RestSharpConsoleApplication.Program.Locations} : RestSharpConsoleApplication.Program.Locations
__invalid_name__98765 : null : RestSharpConsoleApplication.Program.__invalid_type__98765
num_locations : 1 : int
Obviously I am not creating (json2csharp) the right classes for the DeserializeObject, and sadly I have no control over the JSON response (vendor = SimpliSafe).
It is obvious the "98765" is meant to be a value (location number) but json2csharp makes it into this __invalid_type__98765 class and this is probably why it gets null.
Any idea how should the classes look for this particular JSON to be successfully deserialized?
Thanks!
Zachs
You should be able to do this with a dictionary:
public class MyData{
[JsonProperty("locations")]
public Dictionary<string, Location> Locations {get;set;}
}
public class Location
{
public string street1 { get; set; }
public string street2 { get; set; }
public string city { get; set; }
public string state { get; set; }
public string postal_code { get; set; }
public string s_status { get; set; }
public string system_state { get; set; }
}
Do you have a non-Express version of Visual Studio? If so, copy the JSON to clipboard and then go to the Visual Studio menu: Edit >> Paste special >> Paste JSON as classes.
Using that gives:
public class Rootobject {
public int num_locations { get; set; }
public Locations locations { get; set; }
}
public class Locations {
public _98765 _98765 { get; set; }
}
public class _98765 {
public string street1 { get; set; }
public string street2 { get; set; }
public string city { get; set; }
public string state { get; set; }
public string postal_code { get; set; }
public string s_status { get; set; }
public string system_state { get; set; }
}
That suggests your JSON structure is not quite right.
You can also specify the property name via an attribute to use to get around this:
public class RootObject
{
public int num_locations { get; set; }
public Locations locations { get; set; }
}
public class Locations
{
[JsonProperty("98765")]
public LocationInner Inner { get; set; }
}
public class LocationInner
{
public string street1 { get; set; }
public string street2 { get; set; }
public string city { get; set; }
public string state { get; set; }
public string postal_code { get; set; }
public string s_status { get; set; }
public string system_state { get; set; }
}
...but it would really be better if the JSON were properly formatted such that the Locations was actually an array of location objects.