Deserialize Json into a dynamic object with ServiceStack.Text - c#

I am using ServiceStack.Text to deserialize json into a dynamic object.
I'm encountering an error when trying to deserialize the following json:
{
"responseHeader":{
"status":0,
"QTime":3,
"params":{
"q":"*:*",
"indent":"true",
"wt":"json"}},
"response":{"numFound":1,"start":0,"docs":[
{
"id":"1",
"title":["test"],
"_version_":1480260331707039744}]
}}
The json above is a string and this is how I am trying to deserialize it:
DynamicJson dyn = DynamicJson.Deserialize(json);
var response = dyn.response;
But I get an error saying: dyn does not contain a definition for 'response'
dyn does return a type of ServiceStack.DynamicJson with the following value (from debugger):
{"response_header":"{\n \"status\":0,\n \"QTime\":0,\n \"params\":{\n \"q\":\"*:*\",\n \"size\":\"0\",\n \"indent\":\"True\",\n \"start\":\"0\",\n \"wt\":\"json\",\n \"return-fields\":\"\"}}","response":"{\"numFound\":1,\"start\":0,\"docs\":[\n {\n \"id\":\"1\",\n \"title\":[\"test\"],\n \"_version_\":1480260331707039744}]\n }"} ServiceStack.DynamicJson
According to the answer here: Using ServiceStack.Text to deserialize a json string to object that's how its done, but what am I doing wrong here?

Even though DynamicJson.Deserialize does in fact return an instance of DynamicJson, you have to declare dyn as dynamic to treat it dynamically:
dynamic dyn = DynamicJson.Deserialize(json);
var response = dyn.response;
According to the documentation for DynamicObject (which DynamicJson inherits from):
In C#, to enable dynamic behavior for instances of classes derived from the DynamicObject class, you must use the dynamic keyword.
If the expression isn't of type dynamic, static binding will still occur, which is why you're seeing the error.

Related

Deserialize List<T> with type from runtime

I am trying to deserialize a response from an API and the type is retrieved at runtime:
var modelType = Type.GetType($"Namespace.{itemname}").GetType();
Then I call a generic method passing the type in (with refrection). After the API call i try to deserialize it form the response:
var obj= await response.Content.ReadAs<List<T>>();
but it gives this error:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.RuntimeType' because the type requires a JSON string value to deserialize correctly.
I also tryied reading it as string and then using the JsonConvert
var str = await response.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<List<T>>(str);
Also same error. Anybody got any idea how to do it? thanks!
The problem lies in the line var modelType = Type.GetType($"Namespace.{itemname}").GetType();.
This code resolves a type by name (Type.GetType($"Namespace.{itemname}")) but then calls on this Type instance the method GetType. This gives you the type of the instance, which is, confusingly, System.Type or System.RuntimeType, depending upon the framework version.
Removing the extra GetType() should fix the problem.
You cannot use generics with a runtime type. That said, there are serialize/deserialize overloads that takes a type argument.
In your case, since you have a List where T is a runtime type, you'd need reflection to dynamically create your generic type at runtime and then pass it into the second argument:
var listType = typeof(List<>);
var modelType = Type.GetType($"Namespace.{itemname}");
var str = await response.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject(str, listType.MakeGenericType(modelType));

How can I derive a C# dynamic object from a web api JSON reponse?

Most of the time we don't, by default, have defined classes in our static language of choice, which presents white a quandary over how to deserialize the e.g. JSON returned from a call to a public and open wen api, dedicated to no single language, except the "language" of e.g. HTML and JSON.
In .NET, these days, nearly all api queries are done with HttpClient, something like the Google Books API ISBN query below:
public class GoogleBooksClient
{
private const string IsbnUrl = "books/v1/volumes?q=isbn:{0}";
private static HttpClient _client = new HttpClient();
...
public async Task<object> GetDetailsByIsbn(string isbn)
{
var json = await _client.GetStringAsync(string.Format(IsbnUrl, isbn));
dynamic objX = JsonConvert.DeserializeObject(json);
return objX;
}
}
The biggest problem here is that whether objX is declared var', object, or dynamic, it is always a reference to a big, ugly JObject instance when DeserializeObject is called without a known type. In this case, the JSON object returned is incredibly complex, and there be dragons waiting for those who endeavour to write a C# class that the said JSON can be parsed into.
This is an ideal, and intended, opportunity for the use of a C# dynamic object, where as the JSON is parsed, properties (and rarely functions for API responses) can be recursively added to the said dynamic object.
Instead, NewtonSoft.JSON tightly binds the data held by the JSON with the heavy red-tape ligature of a quite opaque Jobject data structure. I'm surprised and disappointed that having come so far, NewtonSoft cannot simply extract a pure dynamic object, without all the obfuscating bureaucracy of their JObject maze.
Is there no other way to simply parse the JSON into a C# dynamic object, just like it would be parsed into an explicitly dynamic JavaScript object in other scenarios?
ADDED: By "obfuscating bureaucracy of their JObject maze", I mean the following code:
var json = JsonConvert.SerializeObject(new Person {Id = 196912135012878, Age = 47, Name = "Brady"});
var jObj = JsonConvert.DeserializeObject(json);
produces a JObject instance that my debugger shows as:
This looks, to me, much more like something that should be used internally during parsing of the JSON, and not an end product of that parsing, which should be a pure representation of only the properties parsed from that JSON. That would ideally be a C# dynamic object with no properties for use by any parser.
Rather than a JObject, you can deserialize to an ExpandoObject, which is supported by Json.NET's built-in converter ExpandoObjectConverter. If an array, you can deserialize to a List<ExpandoObject> then select to a List<dynamic>. If a primitive value, you could return JValue.Value.
For instance, if you know in advance your JSON represents an object, just do:
dynamic dyn = JsonConvert.DeserializeObject<ExpandoObject>(json);
If you don't know in advance what the root JSON container might be, you can load it as a JToken and use the following extension method:
public static class JsonExtensions
{
public static dynamic ToDynamic(this JToken token)
{
if (token == null)
return null;
else if (token is JObject)
return token.ToObject<ExpandoObject>();
else if (token is JArray)
return token.ToObject<List<ExpandoObject>>().Cast<dynamic>().ToList();
else if (token is JValue)
return ((JValue)token).Value;
else
// JConstructor, JRaw
throw new JsonSerializationException(string.Format("Token type not implemented: {0}", token));
}
}
Then do:
dynamic dyn = JsonConvert.DeserializeObject<JToken>(json).ToDynamic();
Sample fiddle.

Deserialize JSON with json.NET into C# dynamic

I have following problem: I have a json file that looks like this
{
"Path": {
"FirstPath": "/1/2/text()"
}
}
If I parse this JSON-File with Newtonsoft like this
dynamic dyn = JObject.Parse(json);
or this
dynamic dyn = JsonConvert.DeserializeObject(json);
I get a dynamic object that needs to be used like this
dyn.Path.FirstPath.Value
How can I get rid of the Value stuff? All of my objects in the JSON end up being a string. I don't want to always write ".Value" at the end if it is not necessary.
I tested this using Newtonsoft 8.0.2 and it works fine.
dynamic dyn = JObject.Parse(json);
string value = dyn.Path.FirstPath;
Value should equal /1/2/text().

Deserialize JSON Object to .Net object with NewtonSoft

I got a json Object that i want to deserialize to its .Net type without casting it.
I think i read somewhere in the doc that you can pass an attribute into the json to tells to the deserializer the .Net object type that it can try to cast.
I can't find the where i read this.
I want to avoid use of
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
To get something like this
MyClass myNewObject = JsonConvert.DeserializeObject(json);
I got my json object from an HttpRequest and want to instantiate the appropriate class from this nested object.
Currently deserialization into an known item work good but need something more flexible without the need to manage all known Object from a parsing method.
You can save the object type in your json string like this.
The settings you have to hand over the converter
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
};
How to serialize with the given settings:
var json = JsonConvert.SerializeObject(data, Settings);
This is what your json string looks like:
{
"$type":"YourNamespaceOfTheClass",
"YourPropertyInTheClass":valueOfProperty
}
How to deserialize with the given settings:
var object = JsonConvert.DeserializeObject(json, Settings);
Now your json string contains not only the serialized object, but also the type of your serialized object. So you don't have to worry about the right type when deserializing your json string.
You can do the following:
dynamic myNewObject = JsonConvert.DeserializeObject(json);
which will return a dynamic object which you can work with.
Console.WriteLine(myNewObject.data[0].description);
Obviously, it will fail if your JSON doesn't contain data array having objects with description property.
You can do something like this:
var result = JsonConvert.DeserializeObject<dynamic>(json);
so you can deserialize any object. Cast dynamic says that you're deserializing an anynymous object with any type which will be known on runtime. It trully works!

Deserialize json passed by javascript to c#

Im currently trying to deserialize json that got bassed by javascript this way:
window.external.handlemessage(json);
And its being handled by c# like this:
public void handlemessage(string json)
{
JavaScriptSerializer deserializer = new JavaScriptSerializer();
Dictionary<string, object> deserializedDictionary1 = (Dictionary<string, object>)deserializer.Deserialize(json, typeof(object));
Dictionary<string, object> deserializedDictionary2 = deserializer.Deserialize<Dictionary<string, object>>(json);
object objDeserialized = deserializer.DeserializeObject(json);
}
The passing works fine with plain text for example but just not with json..
I've tried several things such as the deserialize example i provided in the handlemessage but the json just returns invalid basicly. And several other examples ive tried just didn`t do it either.
I have tried to deserialized the json with java and serialized it again without no results (incase there were some flaw).
Also Im trying to deserialize the data without knowing the json structure.
Is it even possible to pass json by javascript and unserializing it with c#?
Also Im trying to deserialize the data without knowing the json structure.
For that you want to use C#'s dynamic type:
JavaScriptSerializer js = new JavaScriptSerializer();
dynamic v = js.Deserialize<dynamic>("{\"text\" : \"hi\"}");
In fact you can start there for all your data until you understand how the object is being mapped.

Categories

Resources