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();
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 have been trying to set some field values of specific objects in C#.
For other reasons I need to construct a List of values from a string then I want to assign this to a field in an object.
The way I indicate the value type of the list is something like this in string
name:type{listItemName:listItemType{listItemValue}}
This list can be of any type, so it is undetermined until we reach conversion.
I am using
List<dynamic> ldy = new List<dynamic>();
foreach (string listElement in listElements)
{
if (listElement == "") continue;
Type leDataType = GetDataType(listElement);
string leData = GetDataRaw(listElement);
var leDynamic = ConstructDataObject(leDataType, leData, listElement);
ldy.Add(leDynamic);
}
Which ends up with the correct data and with the correct data type when I enquire, however when I am trying to use the resulting ldy list and assign it to a field, of course it acts as a List<object>
thus not allowing me to assign.
Finally so, I am using field.SetValue(targetObject, ldy); to assign the value to the field.
The error message I am getting is
ArgumentException: Object of type 'System.Collections.Generic.List`1[System.Object]' cannot be converted to type 'System.Collections.Generic.List`1[System.Int32]'.
Which to be clear, I do understand and I do understand why, however I dont really see how could I solve this issue, not by solving this nor by changing the fundaments of my code design.
Please help!
As #juharr suggested I have searched for solutions to do this with reflection.
Here is my solution:
private static IList GetTypedList(Type t)
{
var listType = typeof(List<>);
var constructedListType = listType.MakeGenericType(t);
var instance = Activator.CreateInstance(constructedListType);
return (IList)instance;
}
I have two dynamic objects and I'd want to overwrite values of object A with values of object B
The problem is that both are of type dynamic
I managed to extract names of the properties with
TypeDescriptor.GetProperties(oldObject);
but I'm not sure how can I read & set dynamic property of dynamic object
something like oldObject.GetType().GetProperty("Test") won't work since even GetType().GetProperties() return empty collection
Thanks in advance
Below way you can get all the properties and their values.
dynamic dynamicObj = //define it
object obj = dynamicObj;
string[] propertyNames = obj.GetType().GetProperties().Select(p => p.Name).ToArray();
foreach (var name in propertyNames)
{
object value = obj.GetType().GetProperty(name).GetValue(obj, null);
}
Use this for private fields.
obj.GetType().GetProperties(BindingFlags.NonPublic);
I have some methods that execute arbitrary SQL against a database and serialize that data collection into a list of a concrete type. That data is then serialized into JSON and stored in a cell in a table. Later, I need to come back and deserialize that data back into its original collection so that it can be used.
I'm having some issues figuring out how to take a Type object and create a collection of that type in order to deserialize it. Here is how my code operates:
public async Task ExecuteWidget(Guid runGuid, string widgetName, Type type, string sql,
IEnumerable<SqlParameter> parameters)
{
var report = operationsContext.ReportRuns.FirstOrDefault(n => n.RunGuid == runGuid);
CheckReportStatus(report);
var param = parameters.ToList();
var result = edwContext.Database.SqlQuery(type, sql, param.ToArray<object>());
var query = result.GetQuery(param);
var data = await result.ToListAsync();
var widgetData = new ReportRunWidgetData()
{
ReportRunId = report?.ReportRunId ?? -1, // This should never be null.
WidgetName = widgetName,
WidgetData = new JavaScriptSerializer().Serialize(data),
Query = query
};
operationsContext.ReportRunWidgetDatas.Add(widgetData);
await operationsContext.SaveChangesAsync();
}
My fetching logic looks something like this:
public object FetchWidgetData(Guid runGuid, string widgetName, Type dataType)
{
var data = operationsContext.ReportRuns
.Include("ReportRunWidgetDatas")
.FirstOrDefault(n => n.RunGuid == runGuid)?
.ReportRunWidgetDatas.FirstOrDefault(n => n.WidgetName == widgetName)?
.WidgetData;
if (data == null) return null;
var deserialized = new JavaScriptSerializer().Deserialize(data, dataType);
return deserialized;
}
Now when the ExecuteWidget method is called, the type parameter is populated by the widget's DTO datatype. For example HeadlineWidgetDTO. However, the execute command gets the data back as a List<HeadlineWidgetDTO>. When my FetchWidgetData method is called, the dataType supplied is still HeadlineWidgetDTO, but it actually needs to be of type IEnumerable<HeadlineWidgetDTO> to deserialize properly.
Given just the type for an individual data row, how can I create a Type object that is instead a collection of that type?
This is mostly a duplicate of How to use Activator to create an instance of a generic Type and casting it back to that type?, however it's hard to tell.
Basically, if you have a type object Type theType, you need to do something like:
var listType = typeof(List<>);
var typeParams = new [] {theType};
var listOfTType = listType.MakeGenericType(typeParams);
var newListOfT = Activator.CreateInstance(listOfTType);
At that point, you have a variable of type object, but that references an object of type List<WhateverYourTypeIs>. Say, theType is typeof(int), then you will have an object of List<int>. Casting it to something usuable is a whole other question though. If you want to add something to that list, I suspect the best way would be to get a MethodInfo for the Add method and Invoke it.
I thought of another way to do this if the type has a default constructor and isn't too expensive to create. Here's a sample (creating a List<int> - but that's just the way I have it coded):
var type = typeof(int);
var dummy = Activator.CreateInstance(type);
var listOfType = new[] {dummy}.ToList();
When you are finished, the listOfType variable is typed as a List<object> but refers to a List<int>. It's mostly mostly workable - for example, you can call Add(object someObj) on it. You won't get compile type parameter type checking, but you will be able to use it.
Is it possible to return a dynamic object from a json deserialization using json.net? I would like to do something like this:
dynamic jsonResponse = JsonConvert.Deserialize(json);
Console.WriteLine(jsonResponse.message);
Json.NET allows us to do this:
dynamic d = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}");
Console.WriteLine(d.number);
Console.WriteLine(d.str);
Console.WriteLine(d.array.Count);
Output:
1000
string
6
Documentation here: LINQ to JSON with Json.NET
See also JObject.Parse and JArray.Parse
As of Json.NET 4.0 Release 1, there is native dynamic support:
[Test]
public void DynamicDeserialization()
{
dynamic jsonResponse = JsonConvert.DeserializeObject("{\"message\":\"Hi\"}");
jsonResponse.Works = true;
Console.WriteLine(jsonResponse.message); // Hi
Console.WriteLine(jsonResponse.Works); // True
Console.WriteLine(JsonConvert.SerializeObject(jsonResponse)); // {"message":"Hi","Works":true}
Assert.That(jsonResponse, Is.InstanceOf<dynamic>());
Assert.That(jsonResponse, Is.TypeOf<JObject>());
}
And, of course, the best way to get the current version is via NuGet.
Updated (11/12/2014) to address comments:
This works perfectly fine. If you inspect the type in the debugger you will see that the value is, in fact, dynamic. The underlying type is a JObject. If you want to control the type (like specifying ExpandoObject, then do so.
If you just deserialize to dynamic you will get a JObject back. You can get what you want by using an ExpandoObject.
var converter = new ExpandoObjectConverter();
dynamic message = JsonConvert.DeserializeObject<ExpandoObject>(jsonString, converter);
I know this is old post but JsonConvert actually has a different method so it would be
var product = new { Name = "", Price = 0 };
var jsonResponse = JsonConvert.DeserializeAnonymousType(json, product);
Yes you can do it using the JsonConvert.DeserializeObject. To do that, just simple do:
dynamic jsonResponse = JsonConvert.DeserializeObject(json);
Console.WriteLine(jsonResponse["message"]);
Note: At the time I answered this question in 2010, there was no way to deserialize without some sort of type, this allowed you to deserialize without having go define the actual class and allowed an anonymous class to be used to do the deserialization.
You need to have some sort of type to deserialize to. You could do something along the lines of:
var product = new { Name = "", Price = 0 };
dynamic jsonResponse = JsonConvert.Deserialize(json, product.GetType());
My answer is based on a solution for .NET 4.0's build in JSON serializer. Link to deserialize to anonymous types is here:
http://blogs.msdn.com/b/alexghi/archive/2008/12/22/using-anonymous-types-to-deserialize-json-data.aspx
If you use JSON.NET with old version which didn't JObject.
This is another simple way to make a dynamic object from JSON:
https://github.com/chsword/jdynamic
NuGet Install
PM> Install-Package JDynamic
Support using string index to access member like:
dynamic json = new JDynamic("{a:{a:1}}");
Assert.AreEqual(1, json["a"]["a"]);
Test Case
And you can use this util as following :
Get the value directly
dynamic json = new JDynamic("1");
//json.Value
2.Get the member in the json object
dynamic json = new JDynamic("{a:'abc'}");
//json.a is a string "abc"
dynamic json = new JDynamic("{a:3.1416}");
//json.a is 3.1416m
dynamic json = new JDynamic("{a:1}");
//json.a is integer: 1
3.IEnumerable
dynamic json = new JDynamic("[1,2,3]");
/json.Length/json.Count is 3
//And you can use json[0]/ json[2] to get the elements
dynamic json = new JDynamic("{a:[1,2,3]}");
//json.a.Length /json.a.Count is 3.
//And you can use json.a[0]/ json.a[2] to get the elements
dynamic json = new JDynamic("[{b:1},{c:1}]");
//json.Length/json.Count is 2.
//And you can use the json[0].b/json[1].c to get the num.
Other
dynamic json = new JDynamic("{a:{a:1} }");
//json.a.a is 1.
Yes it is possible. I have been doing that all the while.
dynamic Obj = JsonConvert.DeserializeObject(<your json string>);
It is a bit trickier for non native type. Suppose inside your Obj, there is a ClassA, and ClassB objects. They are all converted to JObject. What you need to do is:
ClassA ObjA = Obj.ObjA.ToObject<ClassA>();
ClassB ObjB = Obj.ObjB.ToObject<ClassB>();