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;
}
Related
I am new to C# and JSON and need some help in getting the Key name(s) in a list of a nested JSON object. The keys are dynamic so I won't necessarily know the keys.
sample code I've tried.
```
protected void test()
{
var mystring = #"{
""zone1"": {
""sites"": {
""site1"": {
""to"": ""email1"",
""subject"": ""subjecttxt"",
""link"": ""somesite""
},
""site2"": {
""to"": ""email1"",
""subject"": ""subject"",
""link"": ""somesite""
}
},
""zone2"": {
""to"": ""email1"",
""subject"": ""subject"",
""link"": ""somelink""
}}";
var rss = JObject.Parse(mystring);
foreach (var section in rss)
{
Console.Write(section.Key);
IList<JToken> result = rss["zone1"]["sites"].Children().ToList();
var zone = section.Key;
var site = rss[zone]["sites"];
foreach (var subsite in rss["zone1"]["sites"])
{
var subs = subsite.Parent.ToString();
// some other code
}
}
}
```
Looking for a result:
site1,
site2,
...
I can get the children as IList but looking for something similar to "section.Key" as noted above.
Thank you for your help.
I believe what you are looking for is to get the properties of the sites. Since accessing the rss["zone1"]["sites"] returns a JToken, you will need to convert that to JObject and then use Properties() method to get the data you need.
var sites = ((JObject)rss["zone1"]["sites"]).Properties();
Then you can simply iterate over the IEnumerable<Jproperty> to get the Name of the property or whatever else you need from under it.
To get the section.Key for the sites, you can use the following code.
foreach(var site in (JObject)rss["zone1"]["sites"]) {
Console.WriteLine(site.Key);
}
Output:
site1
site2
Your first call to JObject.Parse already does all the work of converting a string into a structured JSON object. The currently-accepted answer redoes some of this work by (1) turning a structured JSON object back into a string, and then (2) re-parsing it with JObject.Parse. There is a simpler way.
Instead, you can cast the value stored at rss["zone1"]["sites"] into a JObject. (The expression rss["zone1"]["sites"] has type JToken, which is a parent class of JObject, but in this case we happen to know that rss["zone1"]["sites"] is always JSON object, i.e. a collection of key-value pairs. Therefore, this cast is safe to perform.)
This is what the code might look like:
var sites = (JObject) rss["zone1"]["sites"];
foreach (var site in sites)
{
Console.WriteLine(site.Key);
}
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>();
I am having trouble understanding when to use JContainer, JObject, and JToken. I understand from the "standards" that JObject is composed of JProperties and that JToken is the base abstract class for all of the JToken types, but I don't understand JContainer.
I am using C# and I just bought LinqPad Pro 5.
I have a JSON data source in a file, so I'm deserializing that file's contents successfully using this statement:
string json;
using (StreamReader reader = new StreamReader(#"myjsonfile.json"))
{
json = reader.ReadToEnd();
}
At that point, I take the JSON string object and deserialize it to a JObject (and this might be my mistake--perhaps I need to make jsonWork a JToken or JContainer?):
JObject jsonWork = (JObject)JsonConvert.DeserializeObject(json);
In my JSON data (the string represented by JSON), I have three objects--the top-level object look similar to this:
{
"Object1" : { ... },
"Object2" : { ... },
"Object3" : { ... }
}
Each object is composed of all sorts of tokens (arrays, strings, other objects, etc.), so it is dynamic JSON. (I used ellipses as placeholders rather than muddying up this question wit lots of JSON data.)
I want to process "Object1", "Object2", and "Object3" separately using LINQ, however. So, ideally, I would like something like this:
// these lines DO NOT work
var jsonObject1 = jsonWork.Children()["Object1"]
var jsonObject2 = jsonWork.Children()["Object2"]
var jsonObject3 = jsonWork.Children()["Object3"]
But the above lines fail.
I used var above because I have no idea what object type I should be using: JContainer, JObject, or JToken! Just so you know what I want to do, once the above jsonObject# variables are properly assigned, I would like to use LINQ to query the JSON they contain. Here is a very simple example:
var query = from p in jsonObject1
where p.Name == "Name1"
select p
Of course, my LINQ ultimately will filter for JSON arrays, objects, strings, etc., in the jsonObject variable. I think once I get going, I can use LinqPad to help me filter the JSON using LINQ.
I discovered that if I use:
// this line WORKS
var jsonObject1 = ((JObject)jsonWork).["Object1"];
Then I get an JObject type in jsonObject1. Is this the correct approach?
It is unclear to me when/why one would use JContainer when it seems that JToken and JObject objects work with LINQ quite well. What is the purpose of JContainer?
You don't really need to worry about JContainer in most cases. It is there to help organize and structure LINQ-to-JSON into well-factored code.
The JToken hierarchy looks like this:
JToken - abstract base class
JContainer - abstract base class of JTokens that can contain other JTokens
JArray - represents a JSON array (contains an ordered list of JTokens)
JObject - represents a JSON object (contains a collection of JProperties)
JProperty - represents a JSON property (a name/JToken pair inside a JObject)
JValue - represents a primitive JSON value (string, number, boolean, null)
So you see, a JObject is a JContainer, which is a JToken.
Here's the basic rule of thumb:
If you know you have an object (denoted by curly braces { and } in JSON), use JObject
If you know you have an array or list (denoted by square brackets [ and ]), use JArray
If you know you have a primitive value, use JValue
If you don't know what kind of token you have, or want to be able to handle any of the above in a general way, use JToken. You can then check its Type property to determine what kind of token it is and cast it appropriately.
JContainer is a base class for JSON elements that have child items. JObject, JArray, JProperty and JConstructor all inherit from it.
For example, the following code:
(JObject)JsonConvert.DeserializeObject("[1, 2, 3]")
Would throw an InvalidCastException, but if you cast it to a JContainer, it would be fine.
Regarding your original question, if you know you have a JSON object at the top level, you can just use:
var jsonWork = JObject.Parse(json);
var jsonObject1 = jsonWork["Object1"];
Most examples have simple json and I've googled "C# Newtonsoft parse JSON" more than once.
Here's a bit of a json file I was just asked to parse for a csv. The company name value is nested within many arrays / objects so it is semi-complicated in that regard.
{
"page": {
"page": 1,
"pageSize": 250
},
"dataRows": [
{
"columnValues": {
"companyName": [
{
"name": "My Awesome Company",
}
]
}
}
]
}
var jsonFilePath = #"C:\data.json";
var jsonStr = File.ReadAllText(jsonFilePath);
// JObject implementation for getting dataRows JArray - in this case I find it simpler and more readable to use a dynamic cast (below)
//JObject jsonObj = JsonConvert.DeserializeObject<JObject>(jsonStr);
//var dataRows = (JArray)jsonObj["dataRows"];
var dataRows = ((dynamic)JsonConvert.DeserializeObject(jsonStr)).dataRows;
var csvLines = new List<string>();
for (var i = 0; i < dataRows.Count; i++)
{
var name = dataRows[i]["columnValues"]["companyName"][0]["name"].ToString();
// dynamic casting implemntation to get name - in this case, using JObject indexing (above) seems easier
//var name2 = ((dynamic)((dynamic)((dynamic)dataRows[i]).columnValues).companyName[0]).name.ToString();
csvLines.Add(name);
}
File.WriteAllLines($#"C:\data_{DateTime.Now.Ticks}.csv", csvLines);
I have JSON String which I am reading from file.
I don't have the source of the JSON Object.
So I can't call JsonConvert.DeserializeObject.
However I want check if the JSON String has specific structure, if yes, append some string or If not append the structure.
allmodules {
feature: 'test-a'
}
submodules {
//some data
}
Assume if there's not allmodules, I would like to append my structure
allmodules {
feature: 'debug-a'
}
If it's already available, just append feature: 'debug-a'
And so on I have some custom work to do. Is there any efficient way to do this without breaking JSON format. Most of the questions regarding String to Object de-serialization, however as I mentioned I don't have original Object, and can't do that.
You can do this using JObject and doing a little manual parsing. It could look something like this:
public string AppendAllModules(string json)
{
var obj = JObject.Parse(json);
JToken token;
if (obj.TryGetValue("allmodules", out token))
return json;
obj.Add(new JProperty("allmodules", new JObject(new JProperty("feature", "test-a"))));
return obj.ToString();
}
Given:
{
"submodules": {
"name": "yuval"
}
}
Would yield:
{
"submodules": {
"name": "yuval"
},
"allmodules": {
"feature": "test-a"
}
}
I don't have the source of the JSON Object.
No worries, you can simply construct a new C# object that it compatible with the JSON definition. There are a number of options listed at
How to auto-generate a C# class file from a JSON object string
Once you have a compatible C# class in your project, you can deserialize the JSON and manipulate it as an object, just as if you had the original object.
use either JObject.FromObject or JObject.Parse to get your file json string into a JObject.
Then the below example code may help. I am going via an If/else way because you mentioned you can not get the exact structure.
JObject obj = JObject.FromObject(
new {Id = 5, Name = "Foo"}
);
JToken jtok = null;
bool found = obj.TryGetValue("Bar",StringComparison.CurrentCultureIgnoreCase, out jtok);
if (!found)
{
obj.Add("Bar","this is added");
}
else
{
Console.WriteLine(jtok);
}
Console.WriteLine(obj["Bar"]);
Of course after you are done editing your JObject you can use the JObject.ToString() method to get the string representation and send it over to the file.
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"]