Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support new System.Text.Json source generator #777

Open
tranb3r opened this issue Dec 4, 2023 · 9 comments
Open

Support new System.Text.Json source generator #777

tranb3r opened this issue Dec 4, 2023 · 9 comments

Comments

@tranb3r
Copy link
Contributor

tranb3r commented Dec 4, 2023

Hi,

Is there any plan to support the new System.Text.Json source generator, in a future version of Flurl?
https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/

I think it would require new extensions, similar to PostJsonAsync or ReceiveJson, but with an additionnal parameter (either JsonTypeInfo or JsonSerializerContext).
Or maybe it's already supported and I'm missing something?

Thanks

@tmenier
Copy link
Owner

tmenier commented Dec 15, 2023

Not familiar with this, I'll read up on it when I have some time. In a nutshell, what are you looking to accomplish?

@tranb3r
Copy link
Contributor Author

tranb3r commented Dec 15, 2023

Well, basically this new SG eliminates runtime reflection (amongst other improvements).
Which is critical for linker and native-aot stuff (aka the future of .NET).
The article explains the details of it, we can discuss the changes after you read it, nothing urgent.

@wbaldoumas
Copy link

+1 to this one.

Implementing overloads of methods like GetJsonAsync and PostJsonAsync which take in JsonTypeInfo or JsonSerializerContext as parameters will really help folks wanting to leverage source generators for improved JSON serialization performance, as well as AoT (like @tranb3r mentions).

@NotAsea
Copy link

NotAsea commented Jul 25, 2024

I second this. Basically you create overloads that accept JsonTypeInfo<T> as last parameter and just pass directly to Serialize Deserialize method of STG, no other complex stufff involve and suddenly Flurl become safe to trim again, i even suggest consume Stream directly in your response deserialize as STG has async overload for consume BodyStream which mean more async friendlier

@tranb3r
Copy link
Contributor Author

tranb3r commented Nov 19, 2024

@tmenier
With the release of net9, this feature becomes even more important.
Is there a plan to implement these changes and publish a new version of Furl soon?
Thanks

@tranb3r
Copy link
Contributor Author

tranb3r commented Nov 26, 2024

There is actually another solution, which consists in implementing an ISerializer that takes a JsonSerializerContext as constructor parameter, and then uses the JsonSerializerOptions to create a JsonTypeInfo in Serialize or Deserialize. No need for additionnal parameters in PostJsonAsync or ReceiveJson.

Here is my code:

internal class JsonSourceGenSerializer : ISerializer
    {
        private readonly JsonSerializerOptions _jsonSerializerOptions;

        public JsonSourceGenSerializer(JsonSerializerContext jsonSerializerContext)
        {
            _jsonSerializerOptions = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true,
                TypeInfoResolver = jsonSerializerContext
            };
        }

        public string Serialize(object obj)
        {
            var jsonTypeInfo = _jsonSerializerOptions.GetTypeInfo(obj.GetType());
            return JsonSerializer.Serialize(obj, jsonTypeInfo);
        }

        public T Deserialize<T>(string s) => string.IsNullOrWhiteSpace(s) ? default : JsonSerializer.Deserialize(s, (JsonTypeInfo<T>)_jsonSerializerOptions.GetTypeInfo(typeof(T)));

        public T Deserialize<T>(Stream stream) => stream.CanSeek && stream.Length == 0
            ? default
            : JsonSerializer.Deserialize(stream, (JsonTypeInfo<T>)_jsonSerializerOptions.GetTypeInfo(typeof(T)));
    }

...

// get a jsonSerializerContext (from source generator)
// create flurlClient and set JsonSerializer with jsonSerializerContext
flurlClient.WithSettings(settings => settings.JsonSerializer = new JsonSourceGenSerializer(jsonSerializerContext))

@tmenier
Copy link
Owner

tmenier commented Nov 26, 2024

@tranb3r That looks great, hopefully others can benefit. I'll look at incorporating this into the core at some point. (Sorry, haven't had a lot of free time lately.)

@tmenier
Copy link
Owner

tmenier commented Nov 26, 2024

@tranb3r Actually, looking at this more closely, if the goal is to eliminate runtime reflection, isn't obj.GetType() going to be self-defeating?

@tranb3r
Copy link
Contributor Author

tranb3r commented Nov 26, 2024

@tranb3r Actually, looking at this more closely, if the goal is to eliminate runtime reflection, isn't obj.GetType() going to be self-defeating?

Actually, obj.GetType() is not using reflection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants