JSONObject Deserialization Does not Deserialize - c#

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.

Related

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 variable name arrays

I am getting JSON that is being returned from a REST web service for survey responses. It has arrays for the name portion of some of the name value pairs. Additionally the names will be variable depending on the type of questions asked. I'm using JSON.net and trying to deserialize the returned value into some type of object tree that I can walk but can't figure out what structure to use to have it filled in.
I tested the following snippet in LinqPad and fields is always empty. Is there someway to easily read in the variable data or do I have to parse it in code?
void Main() {
string json = #"{
'result_ok':true,
'total_count':'51',
'data':[{
'id':'1',
'status':'Deleted',
'datesubmitted':'2015-01-12 10:43:47',
'[question(3)]':'Red',
'[question(4)]':'Blue',
'[question(18)]':12,
'[variable(\'STANDARD_IP\')]':'127.0.0.1',
'[variable(\'STANDARD_GEOCOUNTRY\')]':'United States'
}]
}";
var responses = JsonConvert.DeserializeObject<RootObject>(json);
responses.Dump();
}
public class RootObject {
public bool result_ok { get; set; }
public string total_count { get; set; }
public List<Response> data { get; set; }
}
public class Response {
public string id { get; set; }
public string status { get; set; }
public string datesubmitted { get; set; }
public List<object> fields = new List<object>();
}
Change the fields property in your Response class to be a Dictionary<string, object>, then mark it with a [JsonExtensionData] attribute like this:
public class Response
{
public string id { get; set; }
public string status { get; set; }
public string datesubmitted { get; set; }
[JsonExtensionData]
public Dictionary<string, object> fields { get; set; }
}
All of the fields with the strange property names will then be placed into the dictionary where you can access them as normal. No extra code is required.
Here is a demo: https://dotnetfiddle.net/1rQUXT

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

How to filter null or empty value from Json string

I have a one Model it's look like
public class DataClass
{
public string Name { get; set; }
public string Address { get; set; }
public string ContactNo { get; set; }
}
and I tried to convert in Json request using below mentioned code.
var l=new List<Data>();
l.Add(new Data(){Name="foo",Address ="bar",ContactNo =123});
l.Add(new Data(){Name="biz",Address ="baz"});
string json=JsonConvert.SerializeObject(l);
it will give me string like
[{"Name":"foo","Address":"bar","ContactNo":"123"},{"Name":"biz","Address":"baz","ContactNo":""}]
in output second ContactNo has a empty string but I don't need the field which has a no value or NULL .
can anyone please tell me what is the best way to avoid NULL or Empty field from Json request?
Thanks in Advance.
Change your model as below
public class Data
{
public string Name { get; set; }
public string Address { get; set; }
public int? ContactNo { get; set; }
}
and then serialize your object as below
var result = JsonConvert.SerializeObject(
l,
new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore
});
I assume you are using Json.Net.
You can use the System.ComponentModel.DefaultValueAttribute. This allows you to mark a property to use a different default value than null.
So, if you want empty strings to be ignored in your JSON output you can update the model class to look like this:
public class DataClass
{
[DefaultValue("")]
public string Name { get; set; }
[DefaultValue("")]
public string Address { get; set; }
[DefaultValue("")]
public string ContactNo { get; set; }
}
Note that the SerializerSettings.DefaultValueHandling must be set to Ignore or IgnoreAndPopulate for this to be picked up.
A more thorough example of various approaches for reducing serialized json size is here:
http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size
1.You may add a flag in the model class.
public class DataClass{
public bool isIllegal{get;set;}
public string Name { get; set; }
public string Address { get; set; }
public string ContactNo { get; set{isIllegal=!string.isNullOrEmpty(value);)}
}
2.You can filter data whose isIllegal is false after JsonConvert.SerializeObject(l).

Categories