Get JProperty from Json Path in Newtonsoft.JSON - c#

I have a JSON path string. Let's say for example:
Property1.Item2 and source JSON of
{
Property1 {
Item1: "Value123",
Item2: "Value111"
}
}
and fetch like so
var property = loadedJson.SelectToken(jsonPath);
// property in this case would be a JValue whose value is "Value111"
I want to select the JProperty pointed to by the path. It currently grabs only the value (JValue). This seems like it would be straight forward, but I cannot find a solution.

After selecting the value token you can use Parent to navigate to the property:
var property = (JProperty)loadedJson.SelectToken(jsonPath)?.Parent;
Fiddle: https://dotnetfiddle.net/lmbEGb

Related

Need to get variable name and its data from json file C#

Example of Json:
{
"typeOfDriver": "selenium",
"goToURL": "url",
}
Basically I need a way to gather the first variable name "typeOfDriver", with the code I'm using right now I just get the data from the element.
Code:
dynamic loadConfig = JsonConvert.DeserializeObject(File.ReadAllText(path + "/" + response));
string typeOfDriver = loadConfig["typeOfDriver"];
Thanks!
Edit: Explained better, I need to know the first line variable name, for example this time is typeOfDriver, another time will be another so I need to know it.
I'd highly recommend making a class to represent the data coming from the JSON file. If the data is dynamic, deserializing to a Dictionary might make the most sense. If you need to traverse the JSON hierarchy, you might want to deserialize to JObject. Anything that's not defined explicitly with Newtonsoft.Json will come back as JObject, so using dynamic isn't really necessary.
You can use JObject for that, parse your JSON and get the name and value from the first property
var json = JObject.Parse(File.ReadAllText(path + "/" + response));
var property = json.Properties().FirstOrDefault();
var name = property.Name; //returns "typeOfDriver" string
var value = property.Value.ToString();
With your current code and deserialize to dynamic it can be the similar
IEnumerable<JProperty> properties = loadConfig.Properties();
var name = properties.FirstOrDefault()?.Name; //returns "typeOfDriver" string
To iterate all properties names you can just go through them in a foreach loop
foreach (var property in loadConfig.Properties())
{
var name = property.Name;
}
Sounds like something you should be doing type-safe-ly. Something like this (don't forget to take using NewtonSoft.Json;):
public class InfoDto {
public string typeOfDriver {get; set;}
public string url {get; set;}
}
// get the string any way you want and then
InfoDto myObject = JsonConvert.DeserializeObject<InfoDto>(someString);
// use myObject.typeOfDriver any way you want ...

Get Key Name from nested json object

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

Get absolute path of JSON object

I have a JSON object:
{
""settings"": {
""general"": {
""database"": { ""type"": ""PostgreSql"" }
}
}
}
The absolute path of my JSON object would look like this: settings/general/database/type
I tried to get all the keys with the first solution of this question:
IList<string> keys = parent.Properties().Select(p => p.Name).ToList();
This didn't work for me. The keys list only contained the first key settings and hasn't got the other ones.
There is a path property which shows the path of the node you are in but it doesn't show the complete path of the JSON object.
How can I get the absolute path like in my example?
In your question you are asking how to get the path to "my JSON object", but your sample JSON actually contains four objects, nested. (Each object begins with { and ends with } in the JSON.) So the path will be different depending on which JSON object you are referring to. It looks like you currently have a reference to the outermost object which you are querying to get the names of its properties. But this won't give you the descendant properties, as you've seen. What you need is to get the Path from the innermost property.
So I think we can boil your question down to this:
Given some JSON, how do I get the full path(s) to the deepest value(s) within the hierarchy (i.e. the leaf nodes)?
You can do that with this LINQ-to-JSON query:
var obj = JObject.Parse(json);
var paths = obj.DescendantsAndSelf()
.OfType<JProperty>()
.Where(jp => jp.Value is JValue)
.Select(jp => jp.Path)
.ToList();
If you only want the first one, then replace .ToList() with .FirstOrDefault().
Note that the path(s) will be returned with dots as delimiters. If you would prefer slashes, then add .Replace('.', '/') to jp.Path within the Select() method call.
Working demo here: https://dotnetfiddle.net/lFXtEE
Your parent object only has one key and that is "settings". Its value is a json object. That object has only one key and that is "general". Its value is a json object. That object has only one key and that is "database". Its value is a json object. You are using nested objects so you have to be specific about 'wanting all the keys' of which object.
The SO answer you referenced is not working because it is only giving you all the keys in your root object as a list of strings.
What you want is a recursive way to get all the "keys" (JProperty.Name).
If you have your JProperty with Name = "type", let us call it JProperty typeProp;. Then typeProp.Parent will get you the JContainer containing ""type"" : ""PostgreSql"" and typeProp.Parent.Parent will get you a JProperty with Name = "database".
So something like this might help (beware, untested):
JToken current = typeProp;
string path = "";
while (current != null)
{
path = current.Name + "/" + path;
if(current.Parent != null) current = current.Parent.Parent;
}
This will leave you with an extra slash on the end like this:
settings/general/database/type/
which you can remove with:
char[] charsToTrim = {'/'};
path.trimEnd(charsToTrim)

c#: read value from json using JToken

I have a json and I want to get a value from a complex object. Here is my json:
{
"a1" : {
"a2" : {
"a3" : "desired_value"
}
}
}
And I want to obtain the value "desired value". I've tried to obtain it with this code:
var token = JToken.Parse(json);
string value = token.Value<string>("a1.a2.a3");
But the value string is null. What should I put in the path so I can read this only once, I mean without getting a token and then iterate trough it's childern and so?
You can use SelectToken in order to select the property using its path and then extract the value from that:
string value = token.SelectToken("a1.a2.a3").Value<string>();
SelectToken will return null if the path isn't found, so you might want to guard against that.
JToken.Value expects a key to be provided, whereas SelectToken supports both keys and paths (a key is a simple path). You are providing a path where a key is expected, which results in a value not being found.
To demonstrate the difference, you could also retrieve the value of a3 like this:
token.SelectToken("a1.a2").Value<string>("a3");
I wouldn't recommend doing it this way, but it does show how paths involve traversal but keys are simple indexers.

JSON.net parent key

I'm having a hard time getting the parent key/property/attribute of my JSON objects using JSON.net. That is, I want the outermost property name, as a string, without knowing beforehand/visually what it is. I'm currently iterating over a set of KeyValuePair items and attempting to, for each of those, log out the parent from something that looks like
{"parentKey":
{
"Name": "Name",
"Id": "123",
"Other": null,
"nestedArr":
[
"idx0",
"idx1",
"idx2"
]
}
}
I've tried both keyValue.Value.Ancestors() and keyValue.Value.Parent. With the former, I'm getting what looks to be the function definition... I'm actually not sure what it is: Newtonsoft.Json.Linq.JToken+<GetAncestors>d_ _ 42. Completely beffuddled by that, because based on the usage examples I've scrounged up here, I'm using it to standard.
With the latter, I log out the entire object, or else what appears to be the entire preceding KeyValuePair, rather than just the string "parentKey", which is what I want. The JSON.net docs aren't the best as far as explicit usage examples and what to expect (or maybe it's just that being new to C#, I can't make sense of them), but in any case, I'm kind of unclear on why this is happening and how to accomplish what I want. This is what I'm trying:
foreach (var keyValue in jObjList[0]) //jObjList is a List<JObject> defined above
{
Console.WriteLine(keyValue.Value.Ancestors());
Console.WriteLine(keyValue.Value.Parent);
if (keyValue.Value.GetType() == typeof(JObject))//same block goes for if it's typeof(JArray)
{
Console.WriteLine(keyValue.Key);
}
}
Edit: in the JSON given, and within the loop defined above, for example, in order to get my parent keys (that's just what I'm calling them), my code simply says, if (keyValue.Value.GetType() == typeof(JObject), write keyValue.Key to the console, and the same goes for if getType() is a JArray. In either case, keyValue.Key is a parent key, if that makes sense. What I mean to say by this is that it is a property that points to another Array or Object. My issue is that, as I'm doing this loop recursively, when I get down to a nested Array or Object, my code has no way of realizing that, although there is a new "parent key" currently, like with nestedArr, for example, the parent key of nestedArr is still "parentKey".
the code is abridged, but that's the idea.
All clarifications and corrections are welcome and appreciated. Thanks.
You are seeing Newtonsoft.Json.Linq.JToken+<GetAncestors>d_ _ 42 for Console.WriteLine(keyValue.Value.Ancestors()) because Ancestors is an IEnumerable<T> whose evaluation is lazy, rather than an explicit collection. What you are seeing is the ToString() output of the not-yet-evaluated enumerable.
If what you want to do is to climb up the parent list of a given JToken and find the lowest parent that has a "parentKey" property, then get the value of that parentKey, then this is how you would do it:
JToken token = keyValue.Value; // Here I'm declaring JToken explicitly for clarity. Normally I would use var token = ...
var parentKey = token.AncestorsAndSelf() // Climb up the json container parent/child hierachy
.Select(p => p.SelectToken("parentKey")) // Get the "parentKey" property in the current parent (if present)
.FirstOrDefault(k => k != null); // Return the first one found.
Console.WriteLine(parentKey);
Update
To get the name of the JSON property highest in the JSON container hierarchy, you would do:
var name = token.AncestorsAndSelf() // Walk up the list of ancestors
.OfType<JProperty>() // For each that is a property
.Select(p => p.Name) // Select the name
.LastOrDefault(); // And return the last (topmost).
Update 2
If you're looking for the first property name that appears in a JSON file, you can do the following, using JContainer.DescendantsAndSelf():
var json = #"[{""parentKey"":
{
""Name"": ""Name"",
""Id"": ""123"",
""Other"": null,
""nestedArr"":
[
""idx0"",
""idx1"",
""idx2""
]
}
}]";
var root = (JContainer)JToken.Parse(json);
var name = root.DescendantsAndSelf() // Loop through tokens in or under the root container, in document order.
.OfType<JProperty>() // For those which are properties
.Select(p => p.Name) // Select the name
.FirstOrDefault(); // And take the first.
Debug.WriteLine(name); // Prints "parentKey"
(JContainer represents a JSON node that can contain child nodes, such as an object or array.)

Categories