MongoDB.Driver.UpdateDefinition from json string - c#

Can i deserialize json string to MongoDB.Driver.UpdateDefinition
I try:
var updateData="{'Description':'Big Description'}";
var obj = BsonSerializer.Deserialize<UpdateDefinition<BsonDocument>>(updateData);
But it not work(

You cannot instantiate UpdateDefinition<T> since it's an abstract class. You can get an instance of JsonUpdateDefinition which represents update operation by using below code:
var updateData = "{'Description':'Big Description'}";
var obj = new JsonUpdateDefinition<BsonDocument>(updateData);
You should also check whether you want to replace existing document using above update definition or just set single field. In that case you need $set operator.

Related

C# Covert Type into IEnumerable of same Type?

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.

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

How to cast to type of object based on the object type?

I want to avoid using the specific type (forgort how I did it before)
var obj = new List<Category>();
obj = (List<Category>)EasyCache.Instance.Item(cacheKey)
Something like: obj = (obj.GetType()???)EasyCache.Instance.Item(cacheKey)
If you don't want to repeat the type name in the assignment you can just combine the declaration and the assignment:
var obj = (List<Category>)EasyCache.Instance.Item(cacheKey)
Note that the empty List<Catgeory> you create is thrown away since you overwrite it in the next line. It seems like you create a new one just to allow the use of var in the declaration.
var and dynamic are great tools, but they should not be used to replace static type checking.
You could use
obj = (dynamic)EasyCache.Instance.Item(cacheKey);
It's not a good way, but it should work.

how to deserialize an anonymus object in c# [duplicate]

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

Is it possible to create an object instance based on a string value denoting its type?

I'm trying to dynamically create an object of a certain type in a LINQ-to-XML query based on a string within my XML document. I'm used to being able to dynamically create an object of any type in PHP and JavaScript by simply being able to write something like:
$obj = new $typeName();
Ideally, I'd like to be able to do something like:
List<someObj> = (from someObjs in XMLfile
select new someObj()
{
Name = (string)someObjs.Element("name"),
NestedObj = new someObjs.Element("nestedObj").Element("type")()
{
NestedName = (string)someObjs.Element("nestedObj").Element("name")
}
}).ToList();
I just can't figure out how to do it without grabbing a hold of the current executing assembly.
You can use:
Activator.CreateInstance(Type.GetType(typeName))
Of course, this only works for types with a parameterless constructor.
Update (initializing the object):
You can use C# 4 dynamic typing features to set properties of the newly created object:
dynamic newObj = Activator.CreateInstance(Type.GetType(typeName));
newObj.NestedName = str;
In the context of a LINQ to XML query, you may have to resort to lambda syntax with explicit body:
var list = XMLFile.Select(someObjs => {
dynamic nestedObj = Activator.CreateInstance(
Type.GetType(someObjs.Element("nestedObj").Element("type")));
nestedObj.NestedName = (string)someObjs.Element("nestedObj").Element("name");
return new someObj {
Name = (string)someObjs.Element("name"),
NestedObj = nestedObj
};
}).ToList();
Use the createinstance method of activator class

Categories