Skip to content

Add ParseValue methods to JsonElement #42755

Closed
@steveharter

Description

@steveharter

Background and Motivation

The System.Text.Json.JsonElement is intended to be obtained from a parent JsonDocument which contains a binary "database" and creates the elements from the database as the document is navigated. When the document is done being used, the Dispose method is called to release the pooled memory allocated for the database.

This works fine when the caller can use the Dispose pattern, however there are cases where Dispose can't be used including usages by the deserializer where property or element types of System.Object create a JsonElement (since the actual type isn't known) and assign it to the property\element.

So to work around the Dispose issue, the serializer does this:

using (JsonDocument document = JsonDocument.ParseValue(ref reader))
{
    return document.RootElement.Clone();	
}

This is not intuitive and is slow since the document and element have no hint that the Dispose pattern is not needed and can't apply optimizations such as avoiding some unnecessary allocs and adding caching for literal values True, False and Null.

Proposed API

Currently there are no "Parse" methods on JsonElement (must go through JsonDocument). So this exposes a ParseValue method that can have optimizations applied. Also, since JsonElement does not implement the Dispose pattern, the usage and memory behavior is more intuitive.

namespace System.Text.Json
{
    public struct JsonElement
    {
        +public static JsonElement ParseValue(ref Utf8JsonReader reader);
        +public static bool TryParseValue(ref Utf8JsonReader reader, [NotNullWhen(true)] out JsonElement? element);
    }
}

No other Parse overloads are provided here since the known scenarios only include the serializer. Here's some possible additions based on JsonDocument:

        public static JsonElement Parse(System.Buffers.ReadOnlySequence<byte> utf8Json, JsonElementOptions options);
        public static JsonElement Parse(System.IO.Stream utf8Json, JsonElementOptions options);
        public static JsonElement Parse(System.ReadOnlyMemory<byte> utf8Json, JsonElementOptions options);
        public static JsonElement Parse(System.ReadOnlyMemory<char> json, JsonElementOptions options);
        public static JsonElement Parse(string json, JsonElementOptions options);
        public static Task<JsonElement> ParseAsync(Stream utf8Json, JsonElementOptions options, CancellationToken cancellationToken));

Usage Examples

The serializer would use it like:

        public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return JsonElement.ParseValue(ref reader);
        }

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions