web-dev-qa-db-ja.com

System.Text.Json.JsonElement ToObjectの回避策

System.Text.JsonのJson.NETのToObject<>()メソッドに相当するものを知りたいです。

Json.NETを使用すると、任意のJTokenを使用してクラスに変換できます。例えば:

_var str = ""; // some json string
var jObj = JObject.Parse(str);
var myClass = jObj["SomeProperty"].ToObject<SomeClass>();
_

.NET Core 3の新しい_System.Text.Json_でこれを行うにはどうすればよいでしょうか

_var str = ""; // some json string
var jDoc = JsonDocument.Parse(str);
var myClass = jDoc.RootElement.GetProperty("SomeProperty"). <-- now what??
_

最初は、jDoc.RootElement.GetPRoperty("SomeProperty")で返されたJsonElementを文字列に変換してから、その文字列を逆シリアル化することを考えていました。しかし、私はそれが最も効率的な方法ではないかもしれないと感じており、それを別の方法で行うためのドキュメントを本当に見つけることができません。

11
Stalfos

同じ問題に遭遇したので、今のところ問題なく機能する拡張メソッドをいくつか作成しました。文字列への追加の割り当てを回避するために、組み込みとしてこれを提供するのは良いことです。

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);
}

次に、次のように使用します。

jDoc.RootElement.GetProperty("SomeProperty").ToObject<SomeClass>();
7
Gary Holland

これに関するオープンな拡張機能があり、現在 。NET Core 5. を対象としています。

暫定的に、byteUtf8JsonReaderの両方がJsonDocumentスパンで直接動作するため、文字列ではなく中間byteバッファに書き込むことでパフォーマンスが向上する可能性があります文字列やcharスパンではなく:

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);
    }       
}

デモフィドル ここ

4
dbc

Dbcの回答と同じですが、動的なreturnTypeを指定できるメソッドが含まれています。

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);
    }       
}
0
Paul