Newtonsoft's JObject: read any property using a string expression - c#

I have a JObject and want to get any property or array element coming from a string expression.
I already know how to do it explicitly, like:
jObject["a"][0]["b");
But I would like to do something like: jObject("a[0].b");
The reason is that I am allowing the user to specify what to gather from the JSON object, rather than hardcoding the operation.

You can use SelectToken
string json = #"{a:[{b:1}]}";
var jobj = JObject.Parse(json);
var token = jobj.SelectToken("a[0].b");
Console.WriteLine(token);

Related

Elegant way to access first child using JSON.NET

I'm a bit confused with the Newtonsoft.Json JObject interface. Say I need to access the 'foo' property of the first child in my JSON object. My C# code:
string json = #"{
'someUnknownKey': { 'foo': 'bar' }
}";
JObject o = JObject.Parse(json);
JObject child = o.First.ToObject<JProperty>().Value.ToObject<JObject>();
string s = child["foo"].ToObject<string>();
This works, but is there a more elegant way to do it, without all the JProperty/JObject conversions?
EDIT: I would like to stress that the key name someUnknownKey is unknown so I can't use it in my code.
I believe you do need a conversion to indicate that you expect the first child token to be a property, but you can do it more simply than your current code:
string json = #"{
'someUnknownKey': { 'foo': 'bar' }
}";
JObject root = JObject.Parse(json);
Console.WriteLine(((JProperty) root.First).Value["foo"]);
Or to break it down slightly more clearly:
JObject root = JObject.Parse(json);
JProperty property = (JProperty) root.First;
Console.WriteLine(property.Value["foo"]);
Another option is to use the Properties() method to ask for the first property instead of the first child token. That way you don't need any conversion.
JObject root = JObject.Parse(json);
Console.WriteLine(root.Properties().First().Value["foo"]);
You can do something like this.
var jtk = o.Descendants().First().Children().First().Value<string>("foo")
You can query the json object as dynamic:
string json = #"{
'someUnknownKey': { 'foo': 'bar' }
}";
dynamic o = JArray.Parse(json);
string child = o.someUnknownKey.foo;
Look here for a reference https://www.newtonsoft.com/json/help/html/QueryJsonDynamic.htm
Alternatively you can use [] to access json properties:
JObject o = JObject.Parse(json);
string value = (string)(o['someUnknownKey']['foo']);

Get properties from dynamic object using startswith

I want to get all properties from json that StartsWith particular text
dynamic results = JsonConvert.DeserializeObject<dynamic>(json);
So now below is what i get in results
{"abc" : "Text", "abcde" : "Text2","prop" : "myprop"}
Is it possible to do something like
results.Where(x => x.StartsWith("abc"))
You could simply use results.GetType().GetProperties(), which will give you an array of properties present in the deserialized JSON object.
You could then iterate over that array to get the PropertyInfo objects whose Name starts with whatever string you want, and call GetValue() to obtain the properties' values of interest.
Or you simply don't deserialize at all, but parse the object and treat it as JSON:
var jObject = JObject.Parse(jsonString);
foreach (var rootProperty in jObject)
{
if (rootProperty.Key.StartsWith("whatever"))
{
var valueOfInterest = rootProperty.Value;
}
}
Simply retrieve the runtime-type of the result-object and query its properties using Type.GetProperties:
var type = results.GetType();
type.GetProperties().Where(x => x.Name.StartsWith("abc"));
EDIT: Because any method called on an instance of dynamic is dynamic as well, you have to cast the result of results.GetType into Type. Otherwise you´ll get a compiler-err stating that you can´t use an anonymous method on a dynamically bound operation.
var type = (Type)results.GetType();

Dynamic variable not working in C# with Json.Net

Can anyone tell me why I get an error when trying to output"dJson2.Type" in the code below?
string Json1= #"[{'Id':1, 'FirstName':'John', 'LastName':'Smith'}, {'Id':2, 'FirstName':'Jane', 'LastName':'Doe'}]";
dynamic dJson1= JsonConvert.DeserializeObject(Json1);
Console.WriteLine(dJson1.GetType());
Console.WriteLine(dJson1.Type);
string Json2 = #"{'Id':1, 'FirstName':'John', 'LastName':'Smith'}";
dynamic dJson2 = JsonConvert.DeserializeObject(Json2);
Console.WriteLine(dJson2.GetType());
Console.WriteLine(dJson2.Type);
The program dies on the Console.WriteLine(dJson2.Type) statement. The output of the program is...
Newtonsoft.Json.Linq.JArray
Array
Newtonsoft.Json.Linq.JObject
(should say Object here, I think)
Inspecting the local variables, dJson2 has a "Type" property with value "Object".
This is because JObject behaves similarly as System.Dynamic.ExpandoObject. Try to change your example to:
string Json2 = #"{'Id':1, 'FirstName':'John', 'LastName':'Smith'}";
dynamic dJson2 = JsonConvert.DeserializeObject(Json2);
dJson2.Type = "mynewfield";
Console.WriteLine(dJson2.GetType());
Console.WriteLine(dJson2.Type);
If you want to get property of underlying type you need to cast it (to JToken or JObject), otherwise requested property will be searched in
IDictionary<string, JToken> that JObject implements.
This example may help:
dynamic oobj = new JObject();
oobj.Type = "TEST";
Console.WriteLine(oobj.Type);
Console.WriteLine(((JObject)oobj).Type);

How can I access this field on json?

I've converted a XML into a JSON:
var json = JsonConvert.SerializeXmlNode(doc);
This is the result:
"author": {
"name": "Hey Guappo",
"yt:userId": "asfajgf346346fghsdgsWfiqcfr1pfQ"
}
and I'd like to access to the yt:userId.
I can't do this in .NET:
dynamic objectParsed = JObject.Parse(json);
var userID= (string)objectParsed.entry.author.yt:userId;
because of :. So how can I manage Namespace in JSON? I have:
var yt = XNamespace.Get("http://gdata.youtube.com/schemas/2007");
but I don't know how to apply it...
Try this:
JObject json = JObject.Parse(json);
string userId = json["author"]["yt:userId"].ToString();
This WILL work with the dynamic just fine. You don't have to use a JObject. In addition, I've highlighted the fact that you can use . notation UP TO your "yt:userId", at which point you need to index by string value.
dynamic objectParsed = JObject.Parse(json);
string userId = json.author["yt:userId"].ToString();
There is really no reason to NOT use a JObject, as Tobberoth pointed out, but there is also no technical restriction on using a dynamic if you prefer.
As a side note, avoid using an explicit cast to string with (string). Always use ToString().

JObject how to read values in the array?

This is the json string:
{"d":[{"numberOfRowsAdded":"26723"}]}
string json = DAO.getUploadDataSummary();
JObject uploadData = JObject.Parse(json);
string array = (string)uploadData.SelectToken("d");
How do I change the code to reader the values in 'numberOfRowsAdded?
JObject uploadData = JObject.Parse(json);
int rowsAdded = Convert.ToInt32((string)uploadData["d"][0]["numberOfRowsAdded"])
You need to cast to JArray:
string json = "{\"d\":[{\"numberOfRowsAdded\":\"26723\"}]}";
JObject parsed = JObject.Parse(json);
JArray array = (JArray) parsed["d"];
Console.WriteLine(array.Count);
You can cast your JObject as a dynamic object.
You can also cast your array to JArray object.
JObject yourObject;
//To access to the properties in "dot" notation use a dynamic object
dynamic obj = yourObject;
//Loop over the array
foreach (dynamic item in obj.d) {
var rows = (int)item.numberOfRowsAdded;
}
I played around with writing a generic method that can read any part of my json string. I tried a lot of the answers on this thread and it did not suit my need. So this is what I came up with. I use the following method in my service layer to read my configuration properties from the json string.
public T getValue<T>(string json,string jsonPropertyName)
{
var parsedResult= JObject.Parse(json);
return parsedResult.SelectToken(jsonPropertyName).ToObject<T>();
}
and this is how you would use it :
var result = service.getValue<List<string>>(json, "propertyName");
So you can use this to get specific properties within your json string and cast it to whatever you need it to be.

Categories