Dynamic variable not working in C# with Json.Net - c#

Can anyone tell me why I get an error when trying to output"dJson2.Type" in the code below?
string Json1= #"[{'Id':1, 'FirstName':'John', 'LastName':'Smith'}, {'Id':2, 'FirstName':'Jane', 'LastName':'Doe'}]";
dynamic dJson1= JsonConvert.DeserializeObject(Json1);
Console.WriteLine(dJson1.GetType());
Console.WriteLine(dJson1.Type);
string Json2 = #"{'Id':1, 'FirstName':'John', 'LastName':'Smith'}";
dynamic dJson2 = JsonConvert.DeserializeObject(Json2);
Console.WriteLine(dJson2.GetType());
Console.WriteLine(dJson2.Type);
The program dies on the Console.WriteLine(dJson2.Type) statement. The output of the program is...
Newtonsoft.Json.Linq.JArray
Array
Newtonsoft.Json.Linq.JObject
(should say Object here, I think)
Inspecting the local variables, dJson2 has a "Type" property with value "Object".

This is because JObject behaves similarly as System.Dynamic.ExpandoObject. Try to change your example to:
string Json2 = #"{'Id':1, 'FirstName':'John', 'LastName':'Smith'}";
dynamic dJson2 = JsonConvert.DeserializeObject(Json2);
dJson2.Type = "mynewfield";
Console.WriteLine(dJson2.GetType());
Console.WriteLine(dJson2.Type);
If you want to get property of underlying type you need to cast it (to JToken or JObject), otherwise requested property will be searched in
IDictionary<string, JToken> that JObject implements.
This example may help:
dynamic oobj = new JObject();
oobj.Type = "TEST";
Console.WriteLine(oobj.Type);
Console.WriteLine(((JObject)oobj).Type);

Related

Read List<double> from Json via Newtonsoft in C#

I would like to read a JSON string via the Newtonsoft Json library. It works fine for any basic datatype, but it does not work for a List<double> or any List for that matter.
The test application looks like the following:
static void main()
{
string jsonString = #"
{
'name': 'set1',
'Xvv': {
'parameter': 'hByT',
'values': '[1,2,3]'
}
}";
JObject Json = JObject.Parse(jsonString);
var name = Json["name"].ToString();
var data = Json["Xvv"]["values"].Value<List<double> >(); // Raises error
}
The last line throws the following exception:
System.InvalidCastException: Invalid cast from 'System.String' to 'System.Collections.Generic.List
Is there a way to access the data directly as a List<double>?
In the example JSON you've provided, values is a string. A proper JSON array would be
'values': [1,2,3]
Anyway, after changing the string to the array, .Value<List<double>>() would throw an exception, that a JArray cannot be cast to a JToken - unfortunately I do not really know, why it does not work.
However, JToken.ToObject<T> does the trick, it
Creates an instance of the specified .NET type from the JToken
(see the documentation for ToObject)
With the line
var data = Json["Xvv"]["values"].ToObject<List<double>>();
you can cast the array correctly.
If an IEnumerable would be fine for you, too, you could also use
var data = Json["Xvv"]["values"].Values<double>();

json to instance using TypeName

I am trying to find a way to create an instance of a class from the full type name of the class and the json representation of the instance.
var classTypeFullName = "something.type";
var classType = Type.GetType(classTypeFullName);
var instanceJson = "{....}";
var classInstance = JsonConvert.DeserializeObject(instanceJson, classType);
My problem is it is always returning a JObject, i need it to return the instance type. If i knew the type before the code ran I would normal just do the following:
var classInstance = JsonConvert.DeserializeObject<T>(instanceJson);
Can anyone help?
In case you are looking for an answer to something like this.
The C# Core2.2 application was not loading the assembly as it was a dependency of a referenced dll. As such the classType was null and therefore the Deserialization was always coming back as a JObject not the expect type.
Try this one, i did it some time ago.
convert yr Json to dynamic dynamicObj, and have the full assembly name
var type = Type.GetType("something.type");
var obj = Convert.ChangeType(dynamicObj.Result, type);

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

How can I access this field on json?

I've converted a XML into a JSON:
var json = JsonConvert.SerializeXmlNode(doc);
This is the result:
"author": {
"name": "Hey Guappo",
"yt:userId": "asfajgf346346fghsdgsWfiqcfr1pfQ"
}
and I'd like to access to the yt:userId.
I can't do this in .NET:
dynamic objectParsed = JObject.Parse(json);
var userID= (string)objectParsed.entry.author.yt:userId;
because of :. So how can I manage Namespace in JSON? I have:
var yt = XNamespace.Get("http://gdata.youtube.com/schemas/2007");
but I don't know how to apply it...
Try this:
JObject json = JObject.Parse(json);
string userId = json["author"]["yt:userId"].ToString();
This WILL work with the dynamic just fine. You don't have to use a JObject. In addition, I've highlighted the fact that you can use . notation UP TO your "yt:userId", at which point you need to index by string value.
dynamic objectParsed = JObject.Parse(json);
string userId = json.author["yt:userId"].ToString();
There is really no reason to NOT use a JObject, as Tobberoth pointed out, but there is also no technical restriction on using a dynamic if you prefer.
As a side note, avoid using an explicit cast to string with (string). Always use ToString().

Categories