System.Text.Json.JsonElement ToObject workaround

后端 未结 3 2033
北恋
北恋 2020-11-28 13:59

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

相关标签:
3条回答
  • 2020-11-28 14:39

    There is an open enhancement about this, currently targeted for Future:

    • 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. As stated in the docs:

    Serializing to UTF-8 is about 5-10% faster than using the string-based methods. The difference is because the bytes (as UTF-8) don't need to be converted to strings (UTF-16).

    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.

    0 讨论(0)
  • 2020-11-28 14:40

    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>();
    
    0 讨论(0)
  • 2020-11-28 14:56

    Same as dbc's answer, just including the methods which allow you to specify a return type via Type returnType.

    public static partial class JsonExtensions
    {
        public static T ToObject<T>(this JsonElement element, JsonSerializerOptions options = null)
        {
            var bufferWriter = new ArrayBufferWriter();
            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);
        }       
    
        public static object ToObject(this JsonElement element, Type returnType, JsonSerializerOptions options = null)
        {
            var bufferWriter = new ArrayBufferWriter();
            using (var writer = new Utf8JsonWriter(bufferWriter))
            {
                element.WriteTo(writer);
            }
    
            return JsonSerializer.Deserialize(bufferWriter.WrittenSpan, 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 讨论(0)
提交回复
热议问题