Deserialization further address of json in c# - c#

I am deserializing a json in c#. but address field needs furher deserialization. help me how to do it
{"Name":"name something",
"Start":"2021-11-10T09:00:00",
"End":"2021-11-14T09:00:00",
"AdditionalInformation":"infoadfasf.",
"Address":{"Information":"Cancha Convive "Parque la Hermandad" colonia El Hogar, Tegucigalpa.","City":"Tegucigalpa, Francisco Moraz\u00e1n","CountryIso2":"HN"}}
i cant get the properties of address, eg address have (city, country..)
my c# code
public class Event
{
public string Name { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
public string AdditionalInformation { get; set; }
public Address1 address1 { get; set; }
}
public class Address1
{
public string Information { get; set; }
public string City { get; set; }
public string CountryIso2 { get; set; }
}
data service for deserialization
public class DataService
{
public async Task<IEnumerable<Event>?> GetEventsAsync()
{
return JsonSerializer.Deserialize<IEnumerable<Event>>(await File.ReadAllTextAsync("Data/Events.json"));
}
}

The Address field in the JSON is unmatched with the address1 in Event model.
1.1. Either rename the property to Address
public class Event
{
...
public Address1 Address { get; set; }
}
1.2. Or using the JsonProperty attribute:
[JsonProperty("Address")]
public Address1 address1 { get; set; }
Would suggest using the approach 1.1 which is declaring the property with Pascal Casing naming, following the C# naming convention.
The provided JSON is an object, but not an array. You should deserialize as Event but not IEnumerable<Event>. Following change requires to change the method signature for GetEventAsync method as well.
public async Task<Event> GetEventAsync()
{
return JsonSerializer.Deserialize<Event>(await File.ReadAllTextAsync("Data/Events.json"));
}

Related

JSONObject Deserialization Does not Deserialize

This stumps me. Here are my simplified C# class definitions:
public class Countries
{
string TotalCount { get; set; }
public List<Ctry> Country { get; set; }
}
public class Ctry
{
string CountryId { get; set; }
string CountryName { get; set; }
}
The REST call I make succeeds and returns the following JSON which I can see in 'content' variable:
{"TotalCount":1,"Country":[{"CountryId":1,"CountryName":"USA"}]}
Here is my c# deserializing code:
var content = response.Content;
countryList = JsonConvert.DeserializeObject<Countries>(content);
After deserialization, I expect the country data to be in countryList object. However no data shows up in countryList! What gives? No exceptions or errors either!
Your issue is that JSON.NET defaults to camel-case property names. This is what your code is looking for by default:
{"country":[{"countryId":"1","countryName":"USA"}]}
You need to manually declare the JSON.NET property names for your model:
public class Countries
{
[JsonProperty(PropertyName = "TotalCount")]
string TotalCount { get; set; }
[JsonProperty(PropertyName = "Country")]
public List<Ctry> Country { get; set; }
}
public class Ctry
{
[JsonProperty(PropertyName = "CountryId")]
string CountryId { get; set; }
[JsonProperty(PropertyName = "CountryName")]
string CountryName { get; set; }
}
I tested this and it works with your data.
As a side note, I declared all of the property names because I like to maintain manual control over the serialization and deserialization, in your case, you could squeak by with just declaring the multi-case words.
You can also fix this by adjusting the protection level for your properties, if you don't want to manually define property names:
public class Countries
{
public string TotalCount { get; set; }
public List<Ctry> Country { get; set; }
}
public class Ctry
{
public string CountryId { get; set; }
public string CountryName { get; set; }
}
This way JSON.NET can match the property names automatically if they are publicly accessible.
#Tom W - JSON.NET will automatically convert types when possible, int to string and string to int are fine.

Deserialize multiple JSON records in C# [duplicate]

This question already has an answer here:
Deserializing JSON into an object
(1 answer)
Closed 5 years ago.
I have the following string of Json records:
{
"records":[
{
"PK":"1_1_8",
"ID":"8",
"DeviceID":"1",
"RootID":"1",
"CustName":"test1",
"CustSurname":"test2",
"Address":"Nisou 1",
"City":"",
"ZipCode":"",
"PhoneNumber":"45646",
"HomePhoneNumber":"",
"Email":"",
"Notes":"",
"Owner":"1",
"LanguageID":"1",
"LanguagePK":"",
"DeletedFlag":"false",
"created":"2017-10-25 10:15:00",
"modified":"2017-10-25 09:35:43"
},
{
"PK":"1_1_33",
"ID":"33",
"DeviceID":"1",
"RootID":"1",
"CustName":"",
"CustSurname":"",
"Address":"",
"City":"",
"ZipCode":"",
"PhoneNumber":"",
"HomePhoneNumber":"",
"Email":"",
"Notes":"",
"Owner":null,
"LanguageID":"0",
"LanguagePK":"",
"DeletedFlag":"true",
"created":"2017-10-25 10:13:54",
"modified":"2017-10-25 10:13:54"
},
{
"PK":"1_1_16",
"ID":"16",
"DeviceID":"1",
"RootID":"1",
"CustName":"Theodosis",
"CustSurname":"",
"Address":"Dali",
"City":"Nicosia",
"ZipCode":"2540",
"PhoneNumber":"45645",
"HomePhoneNumber":"99123456",
"Email":"theodosis#gmail.com",
"Notes":"",
"Owner":"",
"LanguageID":"1",
"LanguagePK":"",
"DeletedFlag":"false",
"created":"2017-10-25 09:36:22",
"modified":"2017-10-25 09:36:22"
}
]
}
I am using Xamarin PCL in C# trying to parse this string into a list of objects.
I have a Customer class:
public class Customer
{
[PrimaryKey]
public string PK { get; set; }
public int DeviceID { get; set; }
public int ID { get; set; }
public string RootID{ get; set; }
public string CustName { get; set; }
public string CustSurname { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public string PhoneNumber { get; set; }
public string HomePhoneNumber { get; set; }
public string Email { get; set; }
public string Notes { get; set; }
public bool Owner { get; set; }
public int LanguageID { get; set; }
public string LanguagePK { get; set; }
public bool DeletedFlag { get; set; }
public DateTime created { get; set; }
public DateTime modified { get; set; }
}
I also tried out having a container class with a list of Customer objects.
public class DataContainer
{
public List<Customer> customers { get; set; }
}
I have seen quite a few of examples online on how to parse this into a list or any workable type but nothing seems to be working for me.
I have tried the following (JsonResults holds the string of Json records):
var observation = JsonConvert.DeserializeObject<DataContainer>(JsonResults);
From other posts, I am not able to access JavaScriptSerializer class from my code, perhaps because of the Xamarin PCL Framework I am using.
Any ideas would be very welcome, as I said I do not mind the format I parse the string into, as long as it's workable.
Thank you.
You would have to make the following changes to your code to make this work.
First and most importantly, you don't have a property customers, you have records, so either rename it
public class DataContainer {
public List<Customer> records { get; set; }
}
or add a JsonProperty attribute
[JsonProperty(PropertyName = "records")]
Secondly, your Owner is a bool in C# and a nullable int (int?) in Json. So either change it in your C# class
public int? Owner { get; set; }
or write a converter to do that (e.g. like here)
[JsonConverter(typeof(NullableIntToBooleanConverter))]
public bool Owner { get; set; }
Here is a working .NetFiddle
The JSON string you provided is a JSON object, which contains a single property called records. records property is a List<Customer>. You can not deserialize the given string directly into DataContainer class that you provided because the property names do not match.
In the Class that your provided it is called customers
public class DataContainer {
public List<Customer> customers { get; set; } //records
}
Or please have a look at the attribute for a bit of advanced mapping
[JsonProperty]
JSON you provided is of the form:
{"records":[{Customer},{Customer},{Customer}]}
But Owner property is "1", null or "". Therefore I would suggest redefining Owner as int? (nullable)
Your string shows one object with a property named records that contains a list of other objects. Your code is trying to deserialize this into an object that doesn't have such a property.
Furthermore, the string contains objects with a property Owner that may be missing or have a numeric value. It's definitely not a bool.
You'll have to change Owner to :
public int? Owner { get; set; }
To deserialize the string, you need an object with a records property:
public class DataContainer
{
public Customer[] records { get; set; }
}
var data=JsonConvert.DeserializeObject<DataContainer>(json);
Debug.Assert(data.records.Length == 3);

Unable to parse JSON with empty array/objects

Trying the parse this json file and it seems to be getting stuck on empty objects and arrays.
{"Unexpected character encountered while parsing value: [. Path 'notes'."}
{
"id":null,
"phone":null,
"name":" ",
"email":null,
"address":null,
"assignee":null,
"notes":[
],
"created_at":null,
"items":{
"0":{
"minimized":false,
"sku":{
"partner_id":null,
"type_id":0,
"errors":{
}
}
}
}
}
CLASSES
public class RootObject
{
public string id { get; set; }
public string phone { get; set; }
public string name { get; set; }
public string email { get; set; }
public string address { get; set; }
public string assignee { get; set; }
public string notes { get; set; }
public string created_at { get; set; }
public Items items { get; set; }
}
public class Items
{
public bool minimized { get; set; }
public Sku sku { get; set; }
}
public class Sku
{
public int partner_id { get; set; }
public int type_id { get; set; }
public Errors errors { get; set; }
}
public class Errors
{
}
The issue appears to be with handling the Notes and Errors property, I've tried to use the following settings as per a few other SO posts but nothing has worked and I am not sure how to get this to deserialize into an object.
RootObject o = JsonConvert.DeserializeObject<RootObject>(json, new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
});
Perhaps someone can help me out because it seems to me JSON.net should be able to handle these properties?
Here's a working dotNetFiddle: https://dotnetfiddle.net/Lnkojw
Here's the output.
NOTE: I put in sample values in your json for your null values so you can see that it is working)
Your class definitions (autogenerated from http://json2csharp.com/ ) need to be modified as shown below.
public class RootObject
{
public string id { get; set; }
public string phone { get; set; }
public string name { get; set; }
public string email { get; set; }
public string address { get; set; }
public string assignee { get; set; }
public List<string> notes { get; set; }
public string created_at { get; set; }
public Dictionary<int,Item> items { get; set; }
}
public class Item
{
public bool minimized { get; set; }
public Sku sku { get; set; }
}
public class Sku
{
public int partner_id { get; set; }
public int type_id { get; set; }
[JsonIgnore]
public object errors { get; set; }
}
Since you have stated in comments that Errors will always be empty, I removed that redundant Errors class you had, with no properties or members. I also set the errors member in the Sku class to be object type in case you get values in future. Finally I set this errors property to [JsonIgnore] so json.net will ignore it for serialization / deserialization
Also Items appears to be Dictionary with an int for key and an Item for Value. So I have changed the definition there also.
Here's the code that deserializes and prints out the values.
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
string json = #"{
""id"":1,
""phone"":""415-000-1234"",
""name"":"" "",
""email"":null,
""address"":null,
""assignee"":null,
""notes"":[
],
""created_at"":null,
""items"":{
""0"":{
""minimized"":false,
""sku"":{
""partner_id"":21,
""type_id"":44,
""errors"":{
}
}
}
}
}";
Console.WriteLine("Deserializing json...");
RootObject o = JsonConvert.DeserializeObject<RootObject>(json, new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
});
Console.WriteLine("Success!");
Console.WriteLine("id #: {0}",o.id);
Console.WriteLine("phone #: {0}",o.phone);
foreach (var item in o.items)
{
Console.WriteLine(" Item #: {0}",item.Key);
if (item.Value != null)
{
Console.WriteLine(" SKU: partner_id: {0}",item.Value.sku.partner_id);
Console.WriteLine(" SKU: type_id: {0}",item.Value.sku.type_id);
}
}
}
}
And once again, here's the output. You can see the json values properly deserialized.
PRO TIPS:
Use a sample json that has values for as many fields as possible, so that http://json2csharp.com/ can generate the proper classes
Whenever you have a nameless property like the items in your json,you will likely need to inspect what http://json2csharp.com/ generated and modify it to be a Dictionary or a NameValuePair or KeyValuePair or something else. It is on a case by case basis. In other words, for 99% of well designed json, you can "plug and play" with http://json2csharp.com/ , for the remaining 1% you will have to customize the classes generated, or your serialization code or both.
The issue seems to be that in your auto-properties for RootObject, you have the notes property listed as a string rather than string[] - if notes are indeed an array of strings, your JSON snippet doesn't show that.
You should also be able to use a List<string> for notes, if you would prefer that.

Deserialize JSON with dynamic objects

I have a JSON object that comes with a long list of area codes. Unfortunately each area code is the object name on a list in the Data object. How do I create a class that will allow RestSharp to deserialize the content?
Here's how my class looks now:
public class phaxioResponse
{
public string success { get; set; }
public string message { get; set; }
public List<areaCode> data { get; set; }
public class areaCode
{
public string city { get; set; }
public string state { get; set; }
}
}
And here's the JSON content:
{
success: true
message: "277 area codes available."
data: {
201: {
city: "Bayonne, Jersey City, Union City"
state: "New Jersey"
}
202: {
city: "Washington"
state: "District Of Columbia"
} [...]
}
Since this JSON is not C# friendly, I had to do a little bit of hackery to make it come out properly. However, the result is quite nice.
var json = JsonConvert.DeserializeObject<dynamic>(sampleJson);
var data = ((JObject)json.data).Children();
var stuff = data.Select(x => new { AreaCode = x.Path.Split('.')[1], City = x.First()["city"], State = x.Last()["state"] });
This code will generate an anonymous type that best represents the data. However, the anonymous type could be easily replaced by a ctor for a more normal DTO class.
The output looks something like this:
your json is incorrect, but if you do correct it you can use a json-to-csharp tool like the one on http://json2csharp.com/ to generate your classes:
public class __invalid_type__201
{
public string city { get; set; }
public string state { get; set; }
}
public class Data
{
public __invalid_type__201 __invalid_name__201 { get; set; }
}
public class RootObject
{
public bool success { get; set; }
public string message { get; set; }
public Data data { get; set; }
}
I don't know anything about RestSharp, but if you're using Newtonsoft on the server side, then you can just pass a JObject to your method. Then you can interrogate the object to see what type of object it really is and use JObject.ToObject() to convert it.
I think using Dictionary<int,areaCode> is the easiest way.
public class phaxioResponse
{
public string success { get; set; }
public string message { get; set; }
public Dictionary<int,areaCode> data { get; set; }
public class areaCode
{
public string city { get; set; }
public string state { get; set; }
}
}
Then:
var res= JsonConvert.DeserializeObject<phaxioResponse>(json);
Console.WriteLine(string.Join(",", res.data));

Conditional validation of subclass

I have ASP.NET MVC 3 application with the following class:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Address HomeAddress { get; set; }
// [Optional("MailingAddrressSameAsHome")] - some custom attribute
public Address MailingAddress { get; set; }
public bool MailingAddrressSameAsHome { get; set; }
}
public class Address
{
[Required]
public string Street { get; set; }
...
}
And now I would like to validate, mailing address only when MailingAddressSameAsHome is false. Unfortunatelly I don't known how to stop validating properties in Address class.
Do you have any ideas?
Did you consider only setting MailingAddress when needed, thus letting the property MailingAddrressSameAsHome be read-only:
public bool MailingAddrressSameAsHome
{
//Null means no MailingAddress, which means: use HomeAddress
get { return MailingAddress == null ; }
}
If so, you can validate MailingAddress whenever present.
Regards,
Morten
You could write this with a custom attribute

Categories