Last active
February 6, 2024 09:10
-
-
Save martincostello/53b10574fbee2d8bc7b0f75bf0855a84 to your computer and use it in GitHub Desktop.
A class for plugging the JSON source generator with Refit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Net; | |
using System.Reflection; | |
using System.Text.Json; | |
using System.Text.Json.Serialization; | |
namespace Refit; | |
/// <summary> | |
/// A class representing an implementation of <see cref="IHttpContentSerializer"/> that can be | |
/// used with the <c>System.Text.Json</c> source generators. This class cannot be inherited. | |
/// </summary> | |
/// <param name="jsonSerializerContext">The <see cref="JsonSerializerContext"/> to use.</param> | |
public sealed class SystemTextJsonContentSerializerForSourceGenerator(JsonSerializerContext jsonSerializerContext) : IHttpContentSerializer | |
{ | |
//// Based on https://github.com/reactiveui/refit/blob/main/Refit/SystemTextJsonContentSerializer.cs | |
private readonly JsonSerializerContext _jsonSerializerContext = jsonSerializerContext; | |
/// <inheritdoc /> | |
public HttpContent ToHttpContent<T>(T item) | |
{ | |
ArgumentNullException.ThrowIfNull(item); | |
#if NET8_0_OR_GREATER | |
var jsonTypeInfo = _jsonSerializerContext.GetTypeInfo(typeof(T)); | |
return System.Net.Http.Json.JsonContent.Create(item, jsonTypeInfo); | |
#else | |
return new JsonContent(item, typeof(T), _jsonSerializerContext); | |
#endif | |
} | |
/// <inheritdoc /> | |
public async Task<T?> FromHttpContentAsync<T>(HttpContent content, CancellationToken cancellationToken = default) | |
{ | |
ArgumentNullException.ThrowIfNull(content); | |
using var stream = await content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); | |
#if NET8_0_OR_GREATER | |
var jsonTypeInfo = _jsonSerializerContext.GetTypeInfo(typeof(T)) as JsonTypeInfo<T>; | |
return await JsonSerializer.DeserializeAsync(stream, jsonTypeInfo, cancellationToken).ConfigureAwait(false); | |
#else | |
object result = await JsonSerializer.DeserializeAsync( | |
stream, | |
typeof(T), | |
_jsonSerializerContext, | |
cancellationToken).ConfigureAwait(false); | |
return (T?)result; | |
#endif | |
} | |
/// <inheritdoc /> | |
public string? GetFieldNameForProperty(PropertyInfo propertyInfo) | |
{ | |
ArgumentNullException.ThrowIfNull(propertyInfo); | |
return propertyInfo | |
.GetCustomAttributes<JsonPropertyNameAttribute>(true) | |
.Select(x => x.Name) | |
.FirstOrDefault(); | |
} | |
#if !NET8_0_OR_GREATER | |
/// <summary> | |
/// Based on https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs. | |
/// </summary> | |
private sealed class JsonContent : HttpContent | |
{ | |
private readonly object _value; | |
private readonly Type _objectType; | |
private readonly JsonSerializerContext _serializerContext; | |
internal JsonContent(object inputValue, Type inputType, JsonSerializerContext context) | |
{ | |
_value = inputValue; | |
_objectType = inputType; | |
_serializerContext = context; | |
Headers.ContentType = new("application/json") { CharSet = "utf-8" }; | |
} | |
protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) | |
{ | |
return JsonSerializer.SerializeAsync(stream, _value, _objectType, _serializerContext, CancellationToken.None); | |
} | |
protected override bool TryComputeLength(out long length) | |
{ | |
length = 0; | |
return false; | |
} | |
} | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for this example! I tried it out with net8.0 and replaced ToHttpContent like:
And deleted the JsonContent implementation. Then used it like: