Jyina
Jyina

Reputation: 2902

Is it possible to deserialize json string into dynamic object using System.Text.Json?

I am using System.Text.Json package to use the serialization and deserialization.

I can deserialize a json string into an object when the type is explicitly specified like below.

var data = JsonSerializer.Deserialize<PersonType>(jsonString);

But the dynamic type does not work. Is it possible to deserialize without having to specify the type? Thank you!

var data = JsonSerializer.Deserialize<dynamic>(jsonString);

Upvotes: 38

Views: 52921

Answers (3)

Patrick Knott
Patrick Knott

Reputation: 1827

Yes, you can do the above JGilmore's answer and get a JsonNode or... JsonObject. But, specifically, you can also get a dynamic if you so desire by specifying object as well:

var jsonString = "{\"foo\": \"bar\"}";
dynamic dynam1 = JsonSerializer.Deserialize<object>(jsonString);
var jsonString2 = Convert.ToString(dynam1);  //Or ToString or Serialize...

To work with a JsonObject instead of a JsonNode, you should get System.Text.Json.Nodes, then:

JsonNode data2 = JsonSerializer.Deserialize<JsonNode>(jsonString);
var jsonObject = data2.AsObject();
var subNode = data2["foo"]  //yay, you got the value as a node... woot...

var objVal = subNode.GetValue<object>(); //wonky hope if you want int, it isn't string.
string objStr = objVal?.ToString();

Upvotes: -2

Ilya Chernomordik
Ilya Chernomordik

Reputation: 30205

I have tried using System.Text.Json in a dynamic way and it just does not work in an easy and meaningful way it seems. So while not a direct answer to your question, but I was "forced" to use the good old Newtonsoft.Json that just works:

dynamic result = JObject.Parse(message);

Upvotes: 2

JGilmore
JGilmore

Reputation: 556

tl:dr JsonNode is the recommended way but dynamic typing with deserializing to ExpandoObject works and I am not sure why.

It is not possible to deserialize to dynamic in the way you want to. JsonSerializer.Deserialize<T>() casts the result of parsing to T. Casting something to dynamic is similar to casting to object

Type dynamic behaves like type object in most circumstances. In particular, any non-null expression can be converted to the dynamic type. The dynamic type differs from object in that operations that contain expressions of type dynamic are not resolved or type checked by the compiler. The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time

docs.

The following code snippet shows this happening with your example.

var jsonString = "{\"foo\": \"bar\"}";
dynamic data = JsonSerializer.Deserialize<dynamic>(jsonString);
Console.WriteLine(data.GetType());

Outputs: System.Text.Json.JsonElement

The recommended approach is to use the new JsonNode which has easy methods for getting values. It works like this:

JsonNode data2 = JsonSerializer.Deserialize<JsonNode>(jsonString);
Console.WriteLine(data2["foo"].GetValue<string>());

And finally trying out this worked for me and gives you want you want but I am struggling to find documentation on why it works because according to this issue it should not be supported but this works for me. My System.Text.Json package is version 4.7.2

dynamic data = JsonSerializer.Deserialize<ExpandoObject>(jsonString);
Console.WriteLine(data.GetType());
Console.WriteLine(data.foo);

Upvotes: 51

Related Questions