Je veux connaître l'équivalent de la méthode ToObject<>()
dans Json.NET pour System.Text.Json.
En utilisant Json.NET, vous pouvez utiliser n'importe quel JToken
et le convertir en classe. PAR EXEMPLE:
var str = ""; // some json string
var jObj = JObject.Parse(str);
var myClass = jObj["SomeProperty"].ToObject<SomeClass>();
Comment pourrions-nous faire cela avec le nouveau System.Text.Json
De .NET Core 3
var str = ""; // some json string
var jDoc = JsonDocument.Parse(str);
var myClass = jDoc.RootElement.GetProperty("SomeProperty"). <-- now what??
Au départ, je pensais que je convertirais simplement le JsonElement
qui est retourné dans jDoc.RootElement.GetPRoperty("SomeProperty")
en une chaîne, puis désérialiser cette chaîne. Mais je pense que ce n'est peut-être pas la méthode la plus efficace, et je ne trouve pas vraiment de documentation pour le faire d'une autre manière.
Je suis tombé sur le même problème, j'ai donc écrit quelques méthodes d'extension qui fonctionnent bien pour l'instant. Ce serait bien s'ils fournissaient cela comme intégré pour éviter l'allocation supplémentaire à une chaîne.
public static T ToObject<T>(this JsonElement element)
{
var json = element.GetRawText();
return JsonSerializer.Deserialize<T>(json);
}
public static T ToObject<T>(this JsonDocument document)
{
var json = document.RootElement.GetRawText();
return JsonSerializer.Deserialize<T>(json);
}
Ensuite, utilisez comme suit:
jDoc.RootElement.GetProperty("SomeProperty").ToObject<SomeClass>();
Il y a une amélioration ouverte à ce sujet, actuellement ciblée pour . NET Core 5. :
Dans l'intervalle, vous pouvez obtenir de meilleures performances en écrivant dans un tampon intermédiaire byte
plutôt que dans une chaîne, car JsonDocument
et Utf8JsonReader
fonctionne directement avec byte
étendues plutôt qu'avec des chaînes ou char
étendues:
public static partial class JsonExtensions
{
public static T ToObject<T>(this JsonElement element, JsonSerializerOptions options = null)
{
var bufferWriter = new ArrayBufferWriter<byte>();
using (var writer = new Utf8JsonWriter(bufferWriter))
element.WriteTo(writer);
return JsonSerializer.Deserialize<T>(bufferWriter.WrittenSpan, options);
}
public static T ToObject<T>(this JsonDocument document, JsonSerializerOptions options = null)
{
if (document == null)
throw new ArgumentNullException(nameof(document));
return document.RootElement.ToObject<T>(options);
}
}
Violon de démonstration ici .
Identique à la réponse de dbc, en incluant juste les méthodes qui vous permettent de spécifier un returnType dynamique.
public static partial class JsonExtensions
{
public static T ToObject<T>(this JsonElement element, JsonSerializerOptions options = null)
{
var bufferWriter = new MemoryStream();
using (var writer = new Utf8JsonWriter(bufferWriter))
{
element.WriteTo(writer);
}
return JsonSerializer.Deserialize<T>(bufferWriter.ToArray(), options);
}
public static T ToObject<T>(this JsonDocument document, JsonSerializerOptions options = null)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}
return document.RootElement.ToObject<T>(options);
}
public static object ToObject(this JsonElement element, Type returnType, JsonSerializerOptions options = null)
{
var bufferWriter = new MemoryStream();
using (var writer = new Utf8JsonWriter(bufferWriter))
{
element.WriteTo(writer);
}
return JsonSerializer.Deserialize(bufferWriter.ToArray(), returnType, options);
}
public static object ToObject(this JsonDocument document, Type returnType, JsonSerializerOptions options = null)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}
return document.RootElement.ToObject(returnType, options);
}
}