C# JSON; Deserialize array that sometimes has an empty value (not null) - c#

I'm trying to deserialize a JSON response and I want a function that detects if the array is empty and if it is not empty I want it to return the values.
The JSON array looks like this when empty:
{"metrics":[]}
And when it is not empty it can look like any of the below:
{"metrics":["flow"]}
{"metrics":["energy"]}
{"metrics":["flow","energy"]}
How can I detect this?
It does not work with NullValueHandling since if the array is empty it is not null, it doesn't have any values at all.
I jus get an error about index is not found.
I am returning the array as a List in my classes.

Assuming you're using Newtonsoft.Json for deserializing the json:
class Data
{
public List<string> Metrics { get; set; }
}
var json = "{\"metrics\":[]}";
var obj = JsonConvert.DeserializeObject<Data>(json);
obj.Metrics will be an empty collection, not null.
Plus, even if it was, you could access it like
var metrics = obj.Metrics ?? new List<string>();

Related

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

Turn a JSON string into a dynamic object

I'm trying to create a dynamic object from a JSON string in C#. But i can't get it done.
Normally i would get a JSON string through a web service call but in this case I simply created a simple class which I turn into a JSON string. Then I try to turn it back into a dynamic object with the exact same structure as if it was an instance of the Entity class. But that's where I'm having trouble.
This is the class that i turn into a JSON string:
public class Entity
{
public String Name = "Wut";
public String[] Scores = {"aaa", "bbb", "ccc"};
}
Then in somewhere in my code i do this:
var ent = new Entity();
// The Serialize returns this:
// "{\"Name\":\"Wut\",\"Scores\":[\"aaa\",\"bbb\",\"ccc\"]}"
var json = new JavaScriptSerializer().Serialize(ent);
dynamic dynamicObject1 = new JavaScriptSerializer().DeserializeObject(json);
dynamic dynamicObject2 = Json.Decode(json);
When I debug this code then i see that the first dynamicObject1 returns a Dictionary. Not really what I'm after.
The second dynamicObject2 looks more like the Entity object. It has a property called Name with a value. It also has a dynamic array called Scores, but for some reason that list turns out to be empty...
Screenshot of empty Scores property in dynamic object:
So I'm not having any luck so far trying to cast a JSON string to a dynamic object. Anyone any idea how I could get this done?
Using Json.Net
dynamic dynamicObject1 = JsonConvert.DeserializeObject(json);
Console.WriteLine(dynamicObject1.Name);
Using Json.Net but deserializing into a ExpandableOBject, a type that is native to C#:
dynamic obj= JsonConvert.DeserializeObject<ExpandoObject>(yourjson);
If the target type is not specified then it will be convert to JObject type instead. Json object has json types attached to every node that can cause problems when converting the object into other dynamic type like mongo bson.

c# Json.net deserializing List<Dictionary<string,object>>

What is the proper way to deserialize this JSON string? It is simply an array of dictionaries where each dict has a "title" and "children" where children is another array of dicts.
I am using this as a TreeView item source, but the treeview only displays the Title1 > Child1 because I assume something is wrong with the deserializing I'm doing. I also try to print out Child1's first child but can't figure out how to do it. The code below has an invalid cast exception.
s = #"[{""title"":""Title1"",""children"":[{""title"":""Child1"",""children"":[{""title"":""grandchild1"",""children"":[{""title"":""Huh""}]}] }] }]";
List<Dictionary<string, object>> marr = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(s);
mTreeView.ItemsSource = marr;
List<Dictionary<string,object>> cs = (List<Dictionary<string,object>>)marr[0]["children"];
Debug.WriteLine(cs[0]["title"]);
Looks to me like you have the following:
class MyObject
{
public string title { get; set; }
public List<MyObject> children { get; set; }
}
var deserialized = JsonConvert.DeserializeObject<List<MyObject>>(s);
And no, there's no dictionary here, because:
Try as I might, I don't see a "dictionary" here so much as a recursive list of the object above, and
This is the actual definition of the object your want out anyway, so you can take advantage of all the benefits of having a real type, rather than just a dictionary of strings.
Note to address your comments: If the JSON string changes, it will not break your code; extraneous properties will be ignored and missing properties will correctly get set to null.
https://codetitans.codeplex.com/
codetitans JSON supports correct parsing of JSON into array/dict of primitives as follows:
JSonReader jr = new JSonReader();
IJSonObject json = jr.ReadAsJSonObject(s);
Debug.WriteLine(json[0]["children"][0]["title"]);
As far as I can tell it is the only C# library that does.
It looks like you can do this with JSON.NET out of box currently
var #object = JsonConvert.DeserializeObject(s)
var slightlyMoreUsefulObject = (JArray)#object;
var actualObject = slightlyMoreUsefulObject[0]
var topLevelTitle = actualObject["title"]
var children = actualObject["children"]
var firstChild = children[0]
var firstChildTitle = firstChild["title"]

JavaScriptSerializer: Serialize a list + a string into JSON

I want to use JavaScriptSerializer to send a package of JSON data that contains both a list of objects as well as a string, identified like ChatLogPath. As far as I can tell, that class can only serialize one object -- being the list -- and if I try to append multiple ones it obviously just creates invalid JSON like {...}{...} which won't work.
Is there any way to do this? I'm insanely new to C# and ASP.NET MVC so forgive me if this is a dumb question :)
Edit: here's my code as of right now.
string chatLogPath = "path_to_a_text_file.txt";
IEnumerable<ChatMessage> q = ...
...
JavaScriptSerializer json = new JavaScriptSerializer();
return json.Serialize(q) + json.Serialize(chatLogPath);
Which will output the array like this in JSON { ... } followed by the chatLogPath { ... }. In other words, it can't work since that's invalid JSON.
The easiest way to get a single JSON object with the array and path together is to create a class or dynamic object with each as a property/field of it.
Class example:
public class ChatInformation {
public IEnumerable<ChatMessage> messages;
public string chatLogPath;
}
...
var output = new ChatInformation {
messages = ...,
chatLogPath = "path_to_a_text_file.txt"
};
return json.Serialize(output);
Dynamic example (requires .NET 4+):
dynamic output = new ExpandoObject {
messages = ...,
chatLogPath = "path_to_a_text_file.txt"
};
return json.Serialize(output);
Anonymous Type example (if you don't care to have another class, nor are you on .NET 4):
var output = new {
messages = ...,
chatLogPath = "path_to_a_text_file.txt"
};
return json.Serialize(output);

getJSON array parameter data in ashx

I'm having problems passing an array parameter to my .ashx handler. Querystring parameters work fine, but I don't know how to access the array from within the ashx file.
My array is a list of strings called list. This is how I call the getJSON method:
jQuery.getJSON('Handlers/AccessoryUpdateHandler.ashx?action=updateselection&a=' + a_sku, function (list) {
//...
});
In AccessoryUpdateHandler.ashx I can get the querystring parameter using context.Request.QueryString["a"];
But how do I get the array data? I've looked at the Request.QueryString object but there's nothing there that looks like my array.
If there's a better way of doing this I'd also be interested to know.
Perhaps you shouldn't rely on QueryString to pass the kind of data. I would advice you to use "POST" method instead. In either case, using the approach you are using, you wont be able to pass the data as an array. Convert the array into a string. A utility like stringify() can come in handy here if you dont want to convert the array into a string manually. When you extract the string from the Request.QueryString or Request.Form (in case you use post) in the handler, you can easily use JavaScriptSerializer to deserialize using a simple C# class that has a schema similar to your json array.
Edited: Illustration
An array like:
var ary = [{ "id": "1", "name": "Mark" }, { "id": "2", "name": "John"}];
can be converted to a string like:
var aryS = "[{\"id\":\"1\",\"name\":\"Mark\"},{\"id\":\"1\",\"name\":\"Mark\"}]";
then, your QueryString can be constructed as:
jQuery.getJSON('Handlers/AccessoryUpdateHandler.ashx?action=updateselection&a=' + aryS, function (list) {
//...
});
when you go to your handler code, you can have a simple class to help you deserialize the data:
class Rec
{
public int Id { get; set; }
public string Name { get; set; }
}
with that in place, the last step to deserialize is:
string s = context.Request.QueryString["a"]; // HttpContext context
var jserializer = new JavaScriptSerializer();
var ary = jserializer.Deserialize<Rec[]>(s);
Note you have to use Rec[] in the Deserialize function since you are deserializing into an array. ary will be an array of Rec with all your data from your javascript array. You need to reference System.Web.Extensions to use JavaScriptSerializer
EDIT:
I thought you were talking about an array of objects. If its just an array of *long*s, the following lines should be sufficient:
string s = context.Request.QueryString["a"]; // HttpContext context
var jserializer = new JavaScriptSerializer();
var ary = jserializer.Deserialize<long[]>(s);
and you dont need to create a class. you would only need that if you had a array of json objects
I don't think your need for passing arrays should dictate whether you use get or post as others suggest.
Using get, the most idiomatic ways is using the same parameter multiple times. e.g.
Handlers/AccessoryUpdateHandler.ashx?a=1&a=2&a=55
In fact in most frameworks(.NET being the exception) when you get a parameter from url you get a array return(often with one item)
My suggestion is you parse context.Request.RawUrl

Categories