I'm having some issues accessing dynamic properties after JSON deserialization. Here is the JSON:
{
"user" : {
"511221" :{
"timestamp" : 1403365646384,
"version" : -81317051,
"email" : "user#name.com",
"name" : "My Name",
"structures" : [ "structure.62dd1ff1-f96b-22e3-8d4e-22000c20725r" ]
}
},
}
There's actually two problems here. First is that "511221" changes for each user. This is given when authenticating. I can't create a user class and then create another class which name keeps changing.
Also, it's a number. AFAIK, there is no way to have a class name as a number. What are my options here? I cannot control what gets returned by the API.
So instead of deserialization into a predefined class, I have a dynamic, like this:
dynamic jsonObject = JsonConvert.DeserializeObject(response);
I want to be able to do this:
string[] structures = jsonObject.user.(authInfo.userid).structures;
In words, I want (authInfo.userid) to input the user id as a string above, however this does not seem possible. I have also tried reflection:
private static object ReflectOnPath(object o, string path)
{
object value = o;
string[] pathComponents = path.Split('.');
foreach (var component in pathComponents)
{
Type type = value.GetType();
System.Reflection.PropertyInfo pi = type.GetProperty(component);
//pi is null here, I have no idea why
value = pi.GetValue(value);
}
return value;
}
So it could be called like this to do the same as shown above:
string[] structures = ReflectOnPath(jsonObject, "user." + authInfo.userid + ".structures") as string[];
However, when this is called, GetProperty() on type (JObject) is null. I know the property "user" exists, but why can't I access it?
You can deserialize your JSON to JObject instead of dynamic, then you can access the property by property name dynamically, for example :
JObject jObject = JsonConvert.DeserializeObject<JObject>(response);
var user = "511221";
var structures = jObject["user"][user]["structures"][0];
//given JSON input as in this question,
//following line will print "structure.62dd1ff1-f96b-22e3-8d4e-22000c20725r"
Console.WriteLine(structures);
Related
My HTTP response data includes a field that is structured as a Dictionary<string,object>. Accessing the Object in debug mode shows me what I expect to see, i.e.
ValueKind = Object:
{ "someProp" : "someValue",
"anotherProp" : "anotherValue" .. }
=> the object therefore contains the large json formatted data that I need to access. However, I can't figure out how to do that .. The commonly suggested method returns null:
var myValue = Odata.GetType().GetProperty("someProp").GetValue(Odata, null);
which makes me think there is something I should be serializing which I am not and regardless how much I tried, I can't find any methods to work.
Here is some more info, if it is not enough I will add whatever is needed. I broke it down a lot to try to show clearly what I am getting each step):
// assume Odata = the Object value from the dictionary
//perform reflection
var type = Odata.GetType() // this gives System.Text.json.JsonElement
//get type properties at runtime
var props = type.GetProperties()
//returns array of 2 :
//System.Text.Json.ValueKind and System.Text.json.JsonElement
//attempting to access my properties in the JsonElement
var someValue= type.GetProperty("someProp").GetValue(Odata,null) //this gives null
I don't necessarily want an exact solution, but pointing me to the right place to read would also be very useful!
When you do GetType().GetProperty() you're using the GetProperty() method from Type class, you're using reflection. You want to use the GetProperty method of JsonElement class instead:
var myValue = Odata.GetProperty("someProp").GetString();
I currently have a json string that looks like this
{
"strA":"somestr",
"strB":{
"strB":"String B",
"strC":"String C",
"sections":[
{
"strD":"...",
"str$":"...",
"myArray":[
{
"name":"xxxx",
"value":"xxxx"
}
]
}
]
}
}
Now the content of this json could change however strB will always be where it is. The value of strB can always change. I would like to get the value of strB as string. I tried doing this
var info = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(str);
string strB = info["strB"].ToString();
but that seems to be wrong . Any idea on how I can extract strB value from this json as a string without creating a deserialization class .
You can use JObject and run linq on it.
JObject json = JObject.Parse(jsonstring);
// access the value like this
json["strB"]
Find some very good example: https://www.newtonsoft.com/json/help/html/QueryingLINQtoJSON.htm
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();
I'm using JSON.NET to deserialize a JSON file to a dynamic object in C#.
Inside a method, I would like to pass in a string and refer to that specified attribute in the dynamic object.
For example:
public void Update(string Key, string Value)
{
File.Key = Value;
}
Where File is the dynamic object, and Key is the string that gets passed in. Say I'd like to pass in the key "foo" and a value of "bar", I would do:
Update("foo", "bar");, however due to the nature of the dynamic object type, this results in
{
"Key":"bar"
}
As opposed to:
{
"foo":"bar"
}
Is it possible to do what I'm asking here with the dynamic object?
I suspect you could use:
public void Update(string key, string Value)
{
File[key] = Value;
}
That depends on how the dynamic object implements indexing, but if this is a Json.NET JObject or similar, I'd expect that to work. It's important to understand that it's not guaranteed to work for general dynamic expressions though.
If you only ever actually need this sort of operation (at least within the class) you might consider using JObject as the field type, and then just exposing it as dynamic when you need to.
Okay so it turns out I'm special. Here's the answer for those that may stumble across this in future,
Turns out you can just use the key like an array index and it works perfectly. So:
File[Key] = Value; Works the way I need as opposed to
File.Key = Value;
Thanks anyway!
You can do it, if you're using JObject from JSON.NET. It does not work with an ExpandoObject.
Example:
void Main()
{
var j = new Newtonsoft.Json.Linq.JObject();
var key = "myKey";
var value = "Hello World!";
j[key] = value;
Console.WriteLine(j["myKey"]);
}
This simple example prints "Hello World!" as expected. Hence
var File = new Newtonsoft.Json.Linq.JObject();
public void Update(string key, string Value)
{
File[key] = Value;
}
does what you expect. If you would declare File in the example above as
dynamic File = new ExpandoObject();
you would get a runtime error:
CS0021 Cannot apply indexing with [] to an expression of type 'ExpandoObject'
I search on Google but the result is misunderstand.
This is a code flow:
public class Store
{
public dynamic GetList(List<string> propertyFields)
{
// Body here
// for in list propertyFields. Such as: ["Code", "Name", "Address", ...]
// dynamic result = ...
// result.Code = "value", result.Name = "abc", result.Address = "homeless", result.... = "..."
// return result
}
}
Method returns a dynamic object.
propertyFields is a list of fields name. When I pass 4 strings in list, dynamic has 4 property fields with value (later).
When I call this method:
Store store = new Store();
var rs = store.GetList(["Code","Name","Address"])
Console.WriteLine(rs[0].Code)
That is my point.
My question: Is it possible to do that in C#?
You have confused dynamic, which is a compiler feature that means "defer type analysis of uses of this object until runtime" with ExpandoObject which means "an object that can have properties added at runtime".
It is an understandable confusion; many languages that lack static type checking also have expando objects.
You need to take a look to ExpandoObject class.
Here is more detailed answer to your question:
Dynamic class creation
What are the true benefits of ExpandoObject?