Json.net ignore null values of child objects - c#

I am new into json.net, so any help would be appreciated.
I am using the net 2.0 version of json.net, because i need to integrate it in Unity3d engine Suggested answer (using nullvaluehandling) just don't work! Should i consider this as restiction of the oldest version?
So, a have an object like this:
Object ()
{
ChildObject ChildObject1;
ChildObject ChildObject2;
}
ChildObject ()
{
Property1;
Property2;
}
I want json.net to serialize only not null properties of all objects, including child objects. So if i instatiate only property1 of ChildObject1 and property2 of ChildObject2, the string from JsonConvert will be like this:
{
"ChildObject1":
{
"Property1": "10"
},
"ChildObject1":
{
"Property2":"20"
}
}
But default behaviour creates string like this:
{
"ChildObject1":
{
"Property1": "10",
"Property2": "null"
},
"ChildObject2":
{
"Property1": "null,
"Property2":"20"
}
}
I know about NullValueHandling, but it is not working corretly in my case! It ignore only null properties of the parent object (object that we are serializing), but if this parent object has some childs, it will not ignore null properties of this child objects. My situation is different.
If even one property of a child object is not null, it serialize it to a string with one not-null property and others null.
UPD example of my code:
i have nested classes
My object is like this:
public class SendedMessage
{
public List<Answer> Answers { get; set; }
public AnswerItem Etalon {get; set;}
}
public class Answer ()
{
public AnswerItem Item { get; set; }
}
public class AnswerItem ()
{
public string ID { get; set; }
public bool Result { get; set; }
public int Number { get; set; }
}
i instatiate a SendedMessage object like this:
new SendedMessage x;
x.Etalon = new AnswerItem();
x.Etalon.Result = true;
than i use
string ignored = JsonConvert.SerializeObject(x,
Formatting.Indented,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
and it make this string:
{ "Etalon": {"ID" = "null", "Result" = "false", Number" = "null"}}
so it really ignore the null object Answers (a List), but do not ignore the null properties of a child objects.
Thanks for help!

use this :
string ignored = sonConvert.SerializeObject(movie,
Formatting.Indented,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
here is the example:
public class Movie
{
public string Name { get; set; }
public string Description { get; set; }
public string Classification { get; set; }
public string Studio { get; set; }
public DateTime? ReleaseDate { get; set; }
public List<string> ReleaseCountries { get; set; }
}
static void Main(string[] args)
{
Movie movie = new Movie();
movie.Name = "Bad Boys III";
movie.Description = "It's no Bad Boys";
string included = JsonConvert.SerializeObject(movie,
Formatting.Indented,new JsonSerializerSettings { });
// {
// "Name": "Bad Boys III",
// "Description": "It's no Bad Boys",
// "Classification": null,
// "Studio": null,
// "ReleaseDate": null,
// "ReleaseCountries": null
// }
string ignored = JsonConvert.SerializeObject(movie,
Formatting.Indented,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
// {
// "Name": "Bad Boys III",
// "Description": "It's no Bad Boys"
// }
}

Related

Working with Irregular nodes/elements in json response from an API

I have a situation while working with a JSON response from an API. To give a background, I am consuming an API from a source using a REST API using 3.5 .net framework.
Below is the part of the JSON output and I am kind of struggling to use it.
a)
"value": {
"Description": "Total Calculated things",
"2018": "5,820,456 ",
"2019": "2,957,447 "
}
The last 2 elements are dynamic, those are tend to change in API response. I was expecting the format like I have mentioned below, but at this point of given time the source provider is not able to change it as the API is used in many other different programs. And Changing the things in the source API will make other program owners to change.
b)
"value": {
"Description": "Total Calculated EQUITY AND LIABILITIES",
"YearData": [ {
"Data": "5,820,456",
"Year": "2018"
},
{
"Data": "2,957,447 ",
"Year": "2019"
} ]
}
Is there any way to overcome such thing> Any way to convert a to b?
EDIT
#Xerillio , Thanks . How can I achieve the same using below JSON format.
var json = #"
{
""entityData"": [
{
""name"": ""Statement of Comprehensive Income"",
""subattrOutput"": [
{
""name"": ""Sales"",
""subattrOutput"": [],
""value"": {
""Description"": ""Sales "",
""2018"": ""8,704,888 "",
""2019"": ""4,760,717 ""
},
""score"": ""99.5"",
""valuetype"": ""object""
},
{
""name"": ""Cost of goods sold"",
""subattrOutput"": [],
""value"": {
""Description"": ""Cost of sales "",
""2018"": ""(6,791,489) "",
""2019"": ""(3,502,785) ""
},
""score"": ""99.75"",
""valuetype"": ""object""
}
],
""value"": null,
""score"": ""98.63"",
""valuetype"": ""object""
}
]
}";
I wish this was more easy, but i just got it here:
class Program
{
static async Task Main(string[] args)
{
string json1 = #"{""value"": {""Description"": ""Total Calculated things"",""2018"": ""5,820,456 "",""2019"": ""2,957,447 ""}}";
string json2 = #"{""value"": {""Description"": ""Total Calculated EQUITY AND LIABILITIES"",""YearData"": [ {""Data"": ""5,820,456"",""Year"": ""2018""},{""Data"": ""2,957,447 "",""Year"": ""2019""} ]}}";
var obj1 = JsonConvert.DeserializeObject<ObjectResult>(json1);
var obj2 = JsonConvert.DeserializeObject<ObjectResult>(json2);
var res1 = CastObject<Result1>(obj1.Value.ToString());
var res2 = CastObject<Result2>(obj2.Value.ToString());
var invalidRes1 = CastObject<Result1>(obj2.Value.ToString());
var invalidRes2 = CastObject<Result2>(obj1.Value.ToString());
Console.WriteLine(res1);
Console.WriteLine(res2);
}
public static T CastObject<T>(string obj)
{
return !TryCastObject(obj, out T result) ? default : result;
}
public static bool TryCastObject<TOut>(string objToCast, out TOut obj)
{
try
{
obj = JsonConvert.DeserializeObject<TOut>(objToCast);
return true;
}
catch
{
obj = default;
return false;
}
}
}
public class ObjectResult
{
public object Value { get; set; }
}
public class Result1
{
[JsonProperty(PropertyName = "description")] public string Description { get; set; }
[JsonProperty(PropertyName = "2018")] public string _2018 { get; set; }
[JsonProperty(PropertyName = "2019")] public string _2019 { get; set; }
}
public class Result2
{
[JsonProperty(PropertyName = "Description")] public string Description { get; set; }
[JsonProperty(PropertyName = "YearData")] public List<YearData> YearData { get; set; }
}
public class YearData
{
[JsonProperty(PropertyName = "Data")] public string Data { get; set; }
[JsonProperty(PropertyName = "Year")] public string Year { get; set; }
}
It is A LOT of work and sincerely, as there more nodes in the json i think that using JObject is the best option, and you will have to do a deserealization in more than 1 step :(
Depending on how large the JSON structure is you could deserialize it into a Dictionary and manually map it to the proper format:
var json = #"
{
""value"": {
""Description"": ""Total Calculated things"",
""2018"": ""5,820,456 "",
""2019"": ""2,957,447 ""
}
}";
var badObj = JsonSerializer.Deserialize<BadFormat>(json);
var result = new WrapperType
{
Value = new ProperlyFormattedType()
};
foreach (var pair in badObj.Value)
{
if (pair.Key == "Description")
{
result.Value.Description = pair.Value;
}
else if (int.TryParse(pair.Key, out int _))
{
result.Value.YearData
.Add(new DatedValues
{
Year = pair.Key,
Data = pair.Value
});
}
}
// Data models...
public class BadFormat
{
[JsonPropertyName("value")]
public Dictionary<string, string> Value { get; set; }
}
public class WrapperType
{
public ProperlyFormattedType Value { get; set; }
}
public class ProperlyFormattedType
{
public string Description { get; set; }
public List<DatedValues> YearData { get; set; } = new List<DatedValues>();
}
public class DatedValues
{
public string Year { get; set; }
public string Data { get; set; }
}
See an example fiddle here.

How to bind property name of the data model object in .net core

I have created a data model class and have another created a property of another class type inside that.
Ex:
public class Properties
{
public string PropertyName { get; set; }
public TypeExt Property { get; set; }
}
public class TypeExt
{
public string DataType { get; set; }
public string DataTypeExt { get; set; }
public string Type { get; set; }
}
Now, when i bind the values, everything works fine except that i need the PropertyName value to come as the Label for Property so that the final Json becomes like this.
{
"Properties":[
{
"Test1Property":{
"DataType":"Unsigned integer ",
"DataTypeExt":"64bit",
"Type":"PM"
}
},
{
"Test2Propert":{
"DataType":"Integer ",
"DataTypeExt":"64bit",
"Type":"PM"
}
}
]
}
One way to get it so you get the PropertyName to be a key is by using a Dictionary as part of your model.
var properties = new Dictionary<string, TypeExt>();
var test1Property = new TypeExt { Type = "PM", DataType = "Integer", DataTypeExt = "64bit" };
var test2Property = new TypeExt { Type = "PM", DataType = "Unsigned Integer", DataTypeExt = "64bit" };
properties.Add("Test1Property", test1Property);
properties.Add("Test2Property", test2Property);
What this results in when serialized is the following. It is a slightly different JSON than what you have above though. Notice that it is no longer an "array-of-objects", but an object that contains properties, each of which are the dictionary keys.
{
"Test1Property" : {
"Type": "PM",
"DataType": "Integer",
"DataTypeExt": "64bit"
},
"Test2Property" : {
"Type": "PM",
"DataType": "Unsigned Integer",
"DataTypeExt": "64bit"
}
}

C# Json.NET Camel Case Complex Object

I'm trying to serialize an object as camelCase and I'm finding that only the objects at the root level are correctly camelCased. Everything below the root level is coming as PascalCase. I'm writing a console application using Json.NET 12.0.3 and .NET Framework 4.0.
public class Deal
{
public string Id { get; set; }
public string Name { get; set; }
public List<PublicId> PublicIds { get; set; }
}
public class PublicId
{
public string IdType { get; set; }
public string Value { get; set; }
}
To serialize I'm using:
var json = JsonConvert.SerializeObject(deal, Formatting.Indented, new JsonSerializerSettings
{
DateFormatString = "yyyy-MM-dd",
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
The result json looks like:
{
"id": null,
"name": "Deal 1",
"publicIds": [
{
"IdType": "ID1",
"Value": "A12"
},
{
"IdType": "ID2",
"Value": "B12"
}
]
}
As you can see the values for IdType and Value are not correctly serialied in camelCase but rather are serialized in PascalCase. There are situations where I'll need to change the serialization between the default PascalCase and camelCase so I won't be able to use JsonProperty annotations to force camelCase during serialization. Additionally I'd like to stick to Json.NET as the only json library for my project.
Is there a clean way to get what I'm looking for?
Firstly I noticed that your Deal class does not initialize PublicIds. In that case the code should actually throw an error.
However, your code that specifies the contract solver CamelCasePropertyNamesContractResolver is correct.
The following is a console code that seems to return proper JSON value.
public class Deal
{
public Deal()
{
PublicIds = new List<PublicId>();
}
public string Id { get; set; }
public string Name { get; set; }
public List<PublicId> PublicIds { get; set; }
}
public class PublicId
{
public string IdType { get; set; }
public string Value { get; set; }
}
Then in the console if the try the code below it seems to yield the desired result.
public static void Main()
{
var deal = new Deal();
deal.Name = "Deal 1";
deal.PublicIds.Add(new PublicId { IdType = "ID1", Value = "A12" });
deal.PublicIds.Add(new PublicId { IdType= "ID2", Value= "B12"});
var json = JsonConvert.SerializeObject(deal, Formatting.Indented, new JsonSerializerSettings
{
DateFormatString = "yyyy-MM-dd",
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
Console.WriteLine(json);
Console.ReadLine();
}
Output by the code:
{
"id": null,
"name": "Deal 1",
"publicIds": [
{
"idType": "ID1",
"value": "A12"
},
{
"idType": "ID2",
"value": "B12"
}
]
}

How to extract those values from the JSON string

I have this JSON string but are not sure how I will parse out the values that are inside:
has
has2
I do succeed to parse out the "id" correctly but are not sure how to access:
CORS
CORS2
CORS3
CORS4
I get the error:
'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.String[]' because the type requires a JSON array (e.g. [1,2,3])
I have pasted the JSON in the pastebin:
https://pastebin.com/iWgGV9VK
The code I have:
public void getInfo()
{
String JSONstring = "{ id: 'hello', name: 'Hello',has:{ CORS: false,CORS2: true},has2:{ CORS3: false,CORS4: true}}";
String id = ""; List<String> has = new List<String>(); List<String> has2 = new List<String>();
var deserializedTicker = JsonConvert.DeserializeObject<JsonInfo>(JSONstring);
id = deserializedTicker.id;
has = deserializedTicker.has.ToList();
has2 = deserializedTicker.has.ToList();
}
public class JsonInfo
{
public String id { get; set; }
public String[] has { get; set; }
public String[] has2 { get; set; }
}
I am trying with the dynamic approach using an object but gets an error here also:
''Newtonsoft.Json.Linq.JValue' does not contain a definition for 'id''
//responseBody holds the JSON string
dynamic stuff = JsonConvert.DeserializeObject(responseBody);
foreach (var info in stuff)
{
dynamic id = info.Value.id; //''Newtonsoft.Json.Linq.JValue' does not contain a definition for 'id''
dynamic has = info.Value.has;
dynamic has2 = info.Value.has2;
if (has != null && has2 != null)
{
dynamic cors = has.CORS;
if(cors != null)
{
MessageBox.Show(cors.ToString());
}
}
}
First off, let's correct your JSON:
{
"id": "hello",
"name": "Hello",
"has": {
"CORS": false,
"CORS2": true
},
"has2": {
"CORS3": false,
"CORS4": true
}
}
Now, the problem you are experiencing is because you are attempting to deserialize the value in "has" and "has2" as arrays. In the JSON, they are not arrays; they are objects. As such, you need to define new classes with the same properties so the JSON can be properly deserialized:
public class JsonInfo
{
public string id { get; set; }
public string name { get; set; }
public JsonHasInfo has { get; set; }
public JsonHas2Info has2 { get; set; }
}
public class JsonHasInfo
{
public bool CORS { get; set; }
public bool CORS2 { get; set; }
}
public class JsonHas2Info
{
public bool CORS3 { get; set; }
public bool CORS4 { get; set; }
}
Now you should be able to deserialize the (correct) JSON properly:
String JSONstring = "{ \"id\": \"hello\", \"name\": \"Hello\", \"has\": { \"CORS\": false, \"CORS2\": true }, \"has2\": { \"CORS3\": false, \"CORS4\": true } }\";"
var deserializedTicker = JsonConvert.DeserializeObject<JsonInfo>(JSONstring);
You json was incorrect, the key has contains a dict no list.
You need change your deserialize to dictionary or change your json.
Here you can see an example:
https://json-schema.org/understanding-json-schema/reference/array.html#array
In your JSON, has is an object, not an array. You should model your class to support an object containing the attributes CORS, CORS2, and so on, and so forth.
Edit: If you want to stick to has being an array, you should change your JSON to match what an array expects, which could be like: has: [ false, true ], and omit the CORS thing.

Json parse sub-collection in c#

How can I do JSON in C# like the data below ?
{
"Aliases": [ "teddy", "freddy", "eddy", "Betty" ],
"Name":"reacher gilt",
"Address":"100 East Way",
"Age":74,
"Bars": {
"items": [
{
"Sub_Property1":"beep",
"Sub_Property2":"boop"
},
{
"Sub_Property1":"meep",
"Sub_Property2":"moop"
},
{
"Sub_Property1":"feep",
"Sub_Property2":"foop"
}
]
}
}
Actually my problem is inside the sub-collection. I saw someone did something
like this
person.Bars.Add("items",
new List<BarClass>(new[]{
new BarClass("beep","boop"),
new BarClass("meep","moop"),
new BarClass("feep","foop"),
}));
So, I have to add new BarClass("beep","boop"), but I need to do something
like this
String [] no1 = {1,2,3}
String [] no2 = {4,5,6}
person.Bars.Add("items",
new List<BarClass>(new[]{
for ()
{
new BarClass(no1[i],no2[i])
}
}));
How can i do this? Thanks and please help..
To read the JSON
The best way to read the whole JSON is to Deserialize it to a native C# object. If you do not already have the classes with your, you can create it in Visual Studio as
Copy your JSON text
Create a new empty class file in VS
Edit > Paste Special > Paste JSON As Classes
Here are the classes
public class Person
{
public string[] Aliases { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
public Bars Bars { get; set; }
}
public class Bars
{
public Item[] items { get; set; }
}
public class Item
{
public string Sub_Property1 { get; set; }
public string Sub_Property2 { get; set; }
}
Now you can use some .NET JSON library to deserialize. JSON.Net aka Newtonsoft JSON is a great library. You get get it from NuGet as well.
Then it's pretty easy to get the C# object from the JSON
//using Newtonsoft.Json;
var jsonString = File.ReadAllText(#"C:\YourDirectory\person.json");
var person = JsonConvert.DeserializeObject<Person>(jsonString);
If you want to read the sub-collection only, you can rather use Linq-to-JSON to read the items directly, like this
//using Newtonsoft.Json.Linq;
var jObject = JObject.Parse(jsonString);
List<Item> details = jObject["Bars"]["items"].ToObject<List<Item>>();
To create the JSON
You first need to create the object, then Serialize to JSON
string[] subProperties1 = new string[] { "1", "2", "3" };
string[] subProperties2 = new string[] { "4", "5", "6" };
Person person = new Person { Name = "Johny", Age = 7, Address = "Earth", Aliases = new string[] { "Sony", "Monty" } };
person.Bars = new Bars {
items = subProperties1.Zip(subProperties2,
(prop1, prop2) => new Item { Sub_Property1 = prop1, Sub_Property2 = prop2 })
.ToArray() };
var json = JsonConvert.SerializeObject(person);
To create the items from your existing string arrays, I have used IEnumerable.Zip function from Linq. You can read about them here.
This is the created JSON data
{
"Aliases": [ "Sony", "Monty" ],
"Name": "Johny",
"Address": "Earth",
"Age": 7,
"Bars": {
"items": [
{
"Sub_Property1": "1",
"Sub_Property2": "4"
},
{
"Sub_Property1": "2",
"Sub_Property2": "5"
},
{
"Sub_Property1": "3",
"Sub_Property2": "6"
}
]
}
}
You should create some classes
public class Person
{
public string Name {get;set;}
public string Address{get;set;}
public int Age {get;set;}
public Header {get;set;}
}
public class Header
{
public Detail[] Details {get;set;}
}
public class Detail
{
public string Sub1 {get;set;}
public string Sub2 {get;set;}
}
Create instance from Person class and initialize to instance after than
JavaScriptSerializer serializer =new JavaScriptSerializer();
var result=serializer.Serialize(instanceOfPerson);
"result" is json data
Assuming that you mean you want to create JSON string, you need to create those classes and use something like Newtonsoft JSON.net:
public class Item
{
public string Sub_Property1 { get; set; }
public string Sub_Property2 { get; set; }
}
public class Bars
{
public List<Item> items { get; set; }
}
public class Person
{
public List<string> Aliases { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
public Bars Bars { get; set; }
}
Please read the documentation here: http://www.newtonsoft.com/json/help/html/Introduction.htm

Categories

Resources