I'm working on a dynamic import proces from Json to object array.
Getting a little bit stuck by creating a List<> based on a string reference to the class object.
I'm importing json data from a REST server and using a business objects list to map the json data to predefined classes that can be configured. I'm using NewtonSoft.Json for the parsing of the data to classes.
string classname = "BusinessObjects.Contact";
Type classtype = Type.GetType(classname);
// ... filled jsonstring from api request
string json = "[]"; // json filled from rest request
JObject obj = JObject.Parse(json);
JArray array = (JArray)obj["contacts"];
// the issue part...
var records = array.ToObject<List<classtype>>();
The compiler states I'm using a variable as a type. Which makes sense, but can't find a way around it.
Any help would be appreciated!
Rather than deserializing your JArray, you could access it dynamically as shown in Querying JSON with dynamic. But if you would prefer to deserialize to a fixed list type, since you are writing non-generic reflection-based code, you can do:
var listType = typeof(List<>).MakeGenericType(classtype);
var records = array.ToObject(listType);
Notes:
Given an open generic type such as List<>, Type.MakeGenericType() creates a closed generic type by substituting the Type argument(s) for the type parameters of the open type.
JToken.ToObject() is a non-generic version of ToObject() that can deserialize to a specified Type.
Once you have created your records list you can cast it to the non-generic IList interface to access collections items.
Sample fiddle with prototype sample JSON and definition for BusinessObjects.Contact.
Related
In my C# lambda I retrieve an item from DynamoDB. It is returned as a Dictionary<string, AttributeValue>. Is there a good way to serialize that to JSON?
The AttributeValue class exposes a bunch of properties to retrieve values of different types. If you do a simple serialization each one of those properties shows up in the JSON, most of them null, and makes a really messy object.
I want it to recognize a map and turn it into a JSON object, recognize a list and turn it into a JSON list. Basically, I want the object the Item represents.
You can use an alternate approach in C# to connect to DynamoDB using the DocumentModel. This DocumentModel has a ToJson() function.
Table table = Table.LoadTable(client, "yourtable");
Document document = table.GetItem(123);
string strJSON = document.ToJson();
I have a dynamic type in C# (Content, a type that inherits DynamicObject). It wraps an inner JSON object containing the data. In TryGetMember I return the requested properties from this inner JSON object. This works just fine in case of simple types (e.g. an int or string property), because .Net converts those values correctly.
But I want to use properties with more complex types:
dynamic content = Content.Load(id);
IEnumerable<Book> bookList = content.Books;
The problem is that in TryGetMember of my class I have no way to know the type that I should convert to (in this case the IEnumerable Book), because binder.ReturnType is always Object. According to this article, this is the normal behavior:
Determining the expected type of a DynamicObject member access
But I find this very hard to believe: how is it possible that the API does not let me know the target type? This way I will have to force developers to use the method syntax to specify the type explicitely:
IEnumerable<Books> bookList = content.Books<IEnumerable<Book>>();
...which is ugly and weird.
You could store Type data alongside the JSON serialized data, but that seems like a rather inefficient method of accomplishing what you're trying to do. If your content isn't truely dynamic (e.g., the content changes, but the basic schema of the object is the same), you could just have precompiled classes for each JSON object type, and serialize the JSON into that class once you receive the data. This way, all of the type data would already be recognized by the compiler at runtime.
It turns out that this is not possible indeed. I ended up creating an extension method (defined in two forms: for dynamic collections and JArrays). That way I can at least get a collection of my Content class and all of the following solutions work:
One line, but a bit long
var members = ((IEnumerable<dynamic>)group.Members).ToContentEnumerable();
Separate lines
IEnumerable<dynamic> members = adminGroup.Members;
foreach (dynamic member in members.ToContentEnumerable())
{
//...
}
Using the method call syntax of the extension method (a bit unusual).
var members = ContentExtensions.ToContentEnumerable(group.Members);
I have a variable of type Object, which holds JSON data. I need to deserialize this JSON data to my Data Contract class, but DataContractJsonSerializer.ReadObject(stream) accepts Stream type as an argument, and I need to pass argument of type Object.
How can I deserialize this data?
Thanks.
var parameters = JsonConvert.DeserializeObject<ClassName>(paramJson);
The function is available in Newtonsoft.Json which is available through nuget.
I am working on a project that communicates a lot of data with a server. This data is in a json format. We end up creating a lot of dummy objects to parse the json data. This leads to having a lot of classes that just contain class members. Is there a better way of doing things?
thanks
Assuming that you are using NewtonSoft's JSON parser or something similar, you have a couple of choices here. The usual use case here is to deserialize to a named type, thus:
var parsedMessage = JsonConvert.DeserializeObject<Message>(content.AsString());
If you have many types for each differnet JSON message type you wish to receive and wish to avoid to, you can do the following:
var parsedMessage = JsonConvert.DeserializeObject<dynamic>(content.AsString());
This will give you a dynamic object that you can inspect and should also work given other Json libraries. Alternatively, NetwtonSoft also provides the following method:
public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject);
This will allow you to deserialize to an anonymously typed object rather than a dynamic object.
I am using JSON.net in a C# Windows Form application to deserialize a JSON string to a dynamic object:
dynamic jsonObj = JsonConvert.DeserializeObject(strJson);
I'm using the following test JSON for testing:
{"payload":"thePayload","number":3,"dialogResult":"one"}
When I run the code, I can indeed access the properties of the dynamic object using an associative array approach:
var x = jsonObj["payload"];
However, if I try to access the content using property names:
var x = jsonObj.payload;
It works but I get the following Exception:
A first chance exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Microsoft.CSharp.dll
Is there a way to change things so I can access the deserialized content in the dynamic object using property names instead of as an associative array, without getting the exception?
I found this SO post on RutimeBinderExceptions:
Accessing properties of anonymous/dynamic types across dll boundaries gives RuntimeBinderException
But I'd prefer not to use the ExpandoObject type and I'm not even sure if it applies to my situation.
UPDATE: Ok, I believe I am having the problem of depicted in the reference SO post above. The context of the call is a callback from the CefSharp browser user control when Javascript calls back into my C# app.
Try working without the dynamic data type:
Dictionary<string, object> theData= new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(jsonString);
string payload = (string)theData["payload"];
int number = (int)theData["number"];
string dialogResult = (string)theData["dialogResult"];
The call to Deserialize() creates a tree of Dictionary that you can traverse at will.