I have the following code:

var model = new{Name = "Alexander"};var serializedModel = JsonSerializer.Serialize(model);var deserializedModel = JsonSerializer.Deserialize<object>(serializedModel);var name = deserializedModel!.GetType().GetProperty("Name");

The name variable is null as the "Name" property doesn't seem to exist. I do not have the model object when deserializing but just the JSON string.

I have tried using JsonConvert.DeserializeObject(serializedModel) from Newtonsoft and that seems to be working fine. However, I want to use System.Text.Json. Also, I have to use .GetType().GetProperty(...) as it's done like that in the external library I'm passing the deserialized object to.

4

Best Answer


JsonSerializer.Deserialize<object>(serializedModel) is equivalent to var JsonSerializer.Deserialize<JsonElement>(serializedModel); so depending on your requirements you can use it:

var deserializedModel = JsonSerializer.Deserialize<JsonElement>(serializedModel);if (deserializedModel.TryGetProperty("Name", out var nameP)){Console.WriteLine(nameP.ToString());}

For experimentation purposes you can use non-generic method and provide Type instance (doubtful that it will be useful in real app):

var deserializedModel = JsonSerializer.Deserialize(serializedModel, model.GetType());

But usually it is better to stick to standard approach and just create class to use for deserialization. I.e.

class MyClass{public string Name { get; set; }}var x = JsonSerializer.Deserialize<MyClass>(serializedModel);

Also you can look in other ways to perform dynamic deserialization via System.Text.Json (including JsonNode and JsonDocument APIs)

You may not know the "original" type that led to the JSON. But if you know something about the shape (such as "it always has a string property called Name") there's nothing stopping you from deserializing to a type that matches that shape. For example:

using System;using System.Text.Json;public class Program{public static void Main(){var model = new{Name = "Alexander"};var serializedModel = JsonSerializer.Serialize(model);var deserializedModel = JsonSerializer.Deserialize<HasName>(serializedModel);SomeExternalLib.Foo(deserializedModel); }}class SomeExternalLib{public static void Foo(object o){var nameProperty = o.GetType().GetProperty("Name");var name = nameProperty.GetValue(o);Console.WriteLine("I got the name: " + name);}}class HasName{public string Name { get; set; }}

Runnable in this fiddle.

After spending some time on the original issue I was able to get it running using Reflection.Emit and that might actually be the only way to achieve what I originally asked for as you have the properties from the JSON and you have to generate a class at runtime that has said properties.

A more detailed answer can be found here: https://stackoverflow.com/a/29428640

If you don't actually need something so complex then you can try to deserialize to ExpandoObject.

you need only one line of code

string name = (string) JsonObject.Parse(serializedModel).AsObject()["Name"]; //"Alexander"

UPDATE

But if you want it the ridiculous way , IMHO this it is

var deserializedModel = JsonSerializer.Deserialize<object>(serializedModel);string name = ((JsonElement)deserializedModel).GetProperty("Name").GetString();

I am sorry but I will never understand why it is working this way. When I am working with text.json I just try to do everything the most akward way, inside out, and it is usully helps. You have to ask a text.json team how they are doing this kind of libraries.

just to compare using newtonsoft and text.json

//using Newtonsoft.Json;string name = (string) JObject.FromObject(model)["Name"];//using System.Text.Json;var serializedModel = JsonSerializer.Serialize(model);string name = JsonSerializer.Deserialize<JsonElement>(serializedModel).GetProperty("Name").GetString();