Dynamically serialise JSON with the ability to omit entries - c#

I am using an API that frustratingly requires you to omit optional parameters rather than pass them as null.
Also, data is slightly nested in the format:
{ data: { prop1: 5, prop2: 6, prop3: 7 } }
Previously I was converting it using a replace:
"{ data: { prop1: {prop1}, prop2: {prop2}, prop3: {prop3} } }"
.Replace("{prop1}", prop1)....
But it turns out that if a value is not provided the API I am sending this to will only accept it if it's not included in the JSON.
Rather than mess around with complex string concatenation (as I am not using model binding), I thought about simply creating a dictionary and serialising it to JSON.
If I do this:
Dictionary<string, int> props = new Dictionary<string, int>
{
{ "prop1", 6 },
{ "prop3", 7 },
};
string json = JsonConvert.SerializeObject(props, Formatting.Indented);
I can serialise whichever props I need nicely. Unfortunately you can see the way I need to send the data is contained within the data property of the json. I would need to put a dictionary inside my dictionary, but the dictionary is defined as string, int so that isn't possible. If I changed the type, then I'd not be able to put my props in.
To solve this I can see 2 possible clean ways:
Dynamically compose a JSON object somehow sorta like XML
eg. new JsonObject().AddNode("data").AddProperty("Prop1", 3).AddProperty("Prop3", 5).... etc.
Serialise from a dictionary object in a way that will let me include the nested property. Or, find a way to assign the json from a non-nested dictionary into the data property of a new json object.
I've not found a way to do this cleanly yet - alternatively another suggestion on solving this issue would be appreciated.

Not sure what your problem is with the dictionary approach. This works fine:
var props = new Dictionary<string, Dictionary<string, int>>
{
{ "data", new Dictionary<string, int>
{
{"prop1", 6},
{"prop3", 7}
}
}
};
var json = JsonConvert.SerializeObject(props, Formatting.Indented);

Related

Output a JSON property name with a dash using an anonymous object

I am using a third party API which is like this below. It uses Json serializer to output
public Output(string name, object value);
I have to place the following json string in my output file from C#
Output("somename", new {my-name : "somevalue"})
The issue is C# does not allow identifiers with dash (-). How do I achieve this ?
Tried putting raw value like below but it adds back slash (\) to the file output which is not going very well.
Output("somename", #"{""my-name"":""somevalue""}")
Any thoughts ?
Since you are using an anonymous object, the simplest workaround would be to create a Dictionary<string, string> instead:
Output("somename", new Dictionary<string, string> { { "my-name", "somevalue" } });
Serialization of a dictionary as a JSON object in which the dictionary keys are mapped to JSON property names is supported by many .Net JSON serializers including json.net and javascriptserializer and even datacontractjsonserializer when UseSimpleDictionaryFormat = true as noted here.
And if you have values of different types and are using a serializer that supports arbitrary polymorphism during serialization (Json.NET and JavaScriptSerializer do) you could use a Dictionary<string, object>:
Output("somename",
new Dictionary<string, object>
{
{ "my-name", "somevalue" },
{ "my-id", 101 },
{ "my-value", value },
});

Correctly iterating through json array

I am trying to parse through an json array and get the values from it but facing some issues.
I have my json that I get as:
[{
"ID1":"1",
"ID2":"2",
"ID3":"3",
"ID4":"4"
},
{
"ID1":"5",
"ID2":"6",
"ID3":"7",
"ID4":"8"
}]
The key ID1, ID2 etc are not fixed. For ex I can also have my json as:
[{
"ID1":"1",
"ID2":"2"
},
{
"ID1":"5",
"ID2":"6"
}]
Or there can be more keys also, ie its dynamic so I cant create a model and map my json to it.
I was trying to deserialize that and get the data by using the following code.:
public IActionResult GetData(string data)
{
//here data is my json
List<string> myList = JsonConvert.DeserializeObject<List<string>>(data);
foreach (string s in myList)
{
//get values here
}
return Json("");
}
But above gives me error when deserializing as:
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while >parsing value: {. Path '', line 1, position 2.'
So I wanted to know how what is the correct method to loop through this json and get key values from it.
Your JSON is a list of object, your issue is that you are trying to deserialize into a list of string. This will not work for obvious reasons.
Instead you want to deserialize into a list of objects, and since your objects keys change the best thing you can use is a Dictionary<string, string>:
var myList = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(data);
Keep in mind that the JSON you posted is a Dictionary<string, string> but as soon as you get integers or bools in that JSON you should change to Dictionary<string, object>
Fiddle here

Convert Dictionary to JSON in C#

first time asking questions here.
I currently have a Dictionary in C# that I want to serialize into JSON using:
Dictionary<string, List<string> myDict = new Dictionary<string, List<string>();
string json = JsonConvert.SerializeObject(myDict);
Works A1, getting results
{"Key1":["Item1","Item2","Item3"],"Key2":["Item1","Item2","Item3"]}
However, I would like to get my JSON response in this format to be usable with Jquery addons:
{"ID":"Key1", "Value": ["Val":"Item1","Val:":"Item2","Val":"Item3"]
}, { "ID":"Key2",
"Value":["Val":"Item1","Val:":"Item2","Val":"Item3"] }
Without having to loop through the dictionary and rebuild it manually. Is there any decent ways to do it?
Thank you

Easily working on a json object

I'm deserializing (or parsing) a json string to a c# object (using Json.NET) and getting a JObject. I want to iterate all the properties with the key "bla", in the same way iterating all xml elements that named "bla" with XElement.Elements("bla").
If it's not possible, I would like to deserialize my json string into a c# object, and work dynamically and recursively on my deserialized json object (my json string can have lists / arrays that can have objects of 2 types.
In the end after editing my object (changing values and removing or adding properties) I need to serialize my object back to a json string.
Which is the best and easiest way to use json serializing and deserializing?
my Json looks like this:
{"Families":{"Family":[{"propA":"dhsj", "propB":"dhdisb"}, {"propA":"krbsbs", "propC":"ksndbd", "propD":"odndns", "Families":{"Family":[....]}}, {"propA":"dhsj", "propB":[{"propA":"dhsj", "propB":"dhdisb"}, {"propA":"krbsbs", "propC":"ksndbd", "propD":"odndns", "Families":{"Family":[....]}}, {"propA":"dhsj", "propB":"fghfgh"}]}]}
in conclusion, the json value is a json object that it's value is a list/array, the list/array can contain 2 "types" of objects, and one of these types also has a property which it's value is a json object that it's value is a list/array, and it goes like this recursively. sometimes the value of one of the props of the type that doesn't have a property which it's value is a json object that it's value is a list/array, can be a list/array itself, that can contain only 1 type of the two mentioned.
If you don't need a strongly-typed object, you can deserialize to a dictionary:
Dictionary<string, object> myObject = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);
And then just use it as a dictionary:
myObject["Property"] = value;
Or
foreach(var propertyKey in myObject.Keys)
{
// do something with each property
Console.WriteLine($"{propertyKey} = {myObject[propertyKey]}");
}
Here's a fiddle
You can serialize it back after you are done
My json looks more like this:
{"Familys":{"Family":[{"propA":"dhsj", "propB":"dhdisb"}, {"propA":"krbsbs", "propC":"ksndbd", "propD":"odndns", "Families":{"Family":[....]}}]}
For JSON like this:
var json = #"{
""Families"":{
""Family"":[
{
""propA"":""Top""
},
{
""propA"":""Top.Lower"",
""Families"":{
""Family"":[
{
""propB"":""propB value""
},
{
""propA"":""Top.Lower.EvenLower"",
""Families"":{
""Family"":[
{
""propA"":""Top.Lower.EvenLower.EvenLower""
}
]
}
}
]
}
}
]
}
}";
Do something like this:
//calling code makes use of "dynamic" to make things clean and readable.
dynamic parsedJson = JsonConvert.DeserializeObject(json);
var allPropAValues = GetPropAValues(parsedJson);
//**** NOTE: this has our extra property ****
var jsonWithExtraStuffProperty = JsonConvert.SerializeObject(parsedJson);
//recursive function that reads AND writes properties
public static List<string> GetPropAValues(dynamic obj)
{
var propAValues = new List<string>();
//**** NOTE: the use of an added property ****
obj.ExtraStuff = new Random().Next();
//if we have a propA value, get it.
if (obj.propA != null)
propAValues.Add(obj.propA.Value);
//iterate through families if there are any. your JSON had Families.Family.
if (obj.Families != null)
foreach (dynamic family in obj.Families.Family)
propAValues.AddRange(GetPropAValues(family));
return propAValues;
}

Serialize array of objects as one object with a named property for each object in C# with JSON serializer

I have a List that, when serialized as JSON gives me an array of objects. However, I need the serialized version to be structured as follows:
{
"item3":{
"id":3,
"name":"monkey"
},
"item4":{
"id":4,
"name":"turtle"
}
}
Currently, the JSON serialization is structured like this:
[
{
"id":3,
"name":"monkey"
},
{
"id":4,
"name":"turtle"
}
]
My goal is to be able to reference the array by item ID instead of numeric index (ie. arr["item3"].name instead of arr[0].name).
You might did that just putting the data into a dictionary is enough for JaveScripySerializer:
var dict = list.ToDictionary(
item => "item" + item.id);
(and serialize dict)
If not:
I don't have a PC handy for an example, but you should be able to:
write a wrapper class that encapsulated the list/array
use the JavaScriptSerializer class
after creating the serializer, associate the wrapper-type with a custom serializer
in the custom serializer, iterate over the data, adding a key to the dictionary per-item, i.e. data.Add("item"+i,list[i]);
You associate custom maps via RegisterConverters: http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.registerconverters.aspx
Note you don't need to write a deserialize unless you need that too.
If you get stuck, I'll try to ad an example later.

Categories