superstator
superstator

Reputation: 3218

Deserialize anonymous type with System.Text.Json

I am updating some apps for .NET Core 3.x, and as part of that I'm trying to move from Json.NET to the new System.Text.Json classes. With Json.NET, I could deserialize an anonymous type like so:

var token = JsonConvert.DeserializeAnonymousType(jsonStr, new { token = "" }).token;

Is there an equivalent method in the new namespace?

Upvotes: 32

Views: 23382

Answers (3)

maf-soft
maf-soft

Reputation: 2552

If you insist on using only what is already provided in System.Text.Json, you could use a tuple, but its restriction makes it almost useless: the JSON items must be named Item1, Item2, and so on, and you cannot have only one item.

var json = @"{""Item1"": ""abc"", ""Item2"": 123}";
var tuple = JsonSerializer.Deserialize<(string, int)>(json, 
    new JsonSerializerOptions { IncludeFields = true });

You could give the elements names, but that only changes the output, you cannot change the JSON naming. Names are just syntactic sugar for tuples and are not available at runtime.

Upvotes: -2

dbc
dbc

Reputation: 116980

As of .Net 5.0, deserialization of immutable types -- and thus anonymous types -- is supported by System.Text.Json. From How to use immutable types and non-public accessors with System.Text.Json:

System.Text.Json can use a parameterized constructor, which makes it possible to deserialize an immutable class or struct. For a class, if the only constructor is a parameterized one, that constructor will be used.

As anonymous types have exactly one constructor, they can now be deserialized successfully. To do so, define a helper method like so:

public static partial class JsonSerializerExtensions
{
    public static T? DeserializeAnonymousType<T>(string json, T anonymousTypeObject, JsonSerializerOptions? options = default)
        => JsonSerializer.Deserialize<T>(json, options);

    public static ValueTask<TValue?> DeserializeAnonymousTypeAsync<TValue>(Stream stream, TValue anonymousTypeObject, JsonSerializerOptions? options = default, CancellationToken cancellationToken = default)
        => JsonSerializer.DeserializeAsync<TValue>(stream, options, cancellationToken); // Method to deserialize from a stream added for completeness
}

And now you can do:

var token = JsonSerializerExtensions.DeserializeAnonymousType(jsonStr, new { token = "" }).token;

Demo fiddle here.

Upvotes: 47

Please try this library I wrote as an extension to System.Text.Json to offer missing features: https://github.com/dahomey-technologies/Dahomey.Json.

You will find support for anonymous types.

Setup json extensions by calling on JsonSerializerOptions the extension method SetupExtensions defined in the namespace Dahomey.Json:

JsonSerializerOptions options = new JsonSerializerOptions();
options.SetupExtensions();

Then serialize your class with the JsonSerializerExtensions static type:

var token = JsonSerializerExtensions.DeserializeAnonymousType(jsonStr, new { token = "" }, options).token;

Upvotes: 1

Related Questions