I want to know the equivalent of the ToObject<>()
method in Json.NET for System.Text.Json.
Using Json.NET you can use any JToken
and convert it to a class. EG:
var str = ""; // some json string
var jObj = JObject.Parse(str);
var myClass = jObj["SomeProperty"].ToObject<SomeClass>();
How would we be able to do this with .NET Core 3's new System.Text.Json
var str = ""; // some json string
var jDoc = JsonDocument.Parse(str);
var myClass = jDoc.RootElement.GetProperty("SomeProperty"). <-- now what??
Initially I was thinking I'd just convert the JsonElement
that is returned in jDoc.RootElement.GetPRoperty("SomeProperty")
to a string and then deserialize that string. But I feel that might not be the most efficient method, and I can't really find documentation on doing it another way.
I came across the same issue, so I wrote some extension methods which work fine for now. It would be nice if they provided this as built in to avoid the additional allocation to a string.
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);
}
Then use as follows:
jDoc.RootElement.GetProperty("SomeProperty").ToObject<SomeClass>();
There is an open enhancement about this, currently targeted for .NET Core 5.0:
- We should be able serialize and serialize from DOM #31274.
In the interim you may get better performance by writing to an intermediate byte
buffer rather than to a string, since both JsonDocument
and Utf8JsonReader
work directly with byte
spans rather than strings or char
spans:
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);
}
}
Demo fiddle here.