Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[System.Text.Json] Consider adding a feature JsonSerializer to allow deserializing JsonElement #37564

Open
pranavkm opened this issue May 9, 2019 · 3 comments

Comments

@pranavkm
Copy link

commented May 9, 2019

Probably the same as this - #36169, but better worded. It would be useful to have an API that allows deserializing JsonElement in to "T" e.g.

JsonElement element = jsonDocument.Root[0];
SomePoco poco = JsonSerializer.Parse<SomePoco>(element);

Right now the only way to do this is to get to the raw text of the element which just results in needless allocations:

JsonElement element = jsonDocument.Root[0];
SomePoco poco = JsonSerializer.Parse<SomePoco>(element.GetRawText());
@pranavkm

This comment has been minimized.

Copy link
Author

commented May 9, 2019

@ahsonkhan ahsonkhan added this to the 3.0 milestone May 9, 2019

@ahsonkhan

This comment has been minimized.

Copy link
Member

commented May 9, 2019

Also cc @bartonjs - maybe this is additional motivation/reason to expose RawUtf8Bytes (as an alternative). Otherwise, it would be an internal API that the serializer would leverage.

Edit: The deserializer calling an onternal API should work just fine here.

@ahsonkhan ahsonkhan modified the milestones: 3.0, Future May 28, 2019

@stephentoub stephentoub modified the milestones: Future, 5.0 Jul 18, 2019

@peters

This comment has been minimized.

Copy link

commented Sep 11, 2019

@ahsonkhan Allocation "free" version:

using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.Json;

namespace chaos.Serialization
{
    [SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
    [SuppressMessage("ReSharper", "UnusedMember.Local")]
    [SuppressMessage("ReSharper", "UnusedMember.Global")]
    internal readonly ref struct JsonElementSerializer
    {
        static readonly FieldInfo JsonDocumentField = typeof(JsonElement).GetField("_parent", BindingFlags.NonPublic | BindingFlags.Instance);
        static readonly FieldInfo JsonDocumentUtf8JsonField = typeof(JsonDocument).GetField("_utf8Json", BindingFlags.NonPublic | BindingFlags.Instance);

        ReadOnlyMemory<byte> Value { get; }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public JsonElementSerializer(JsonElement jsonElement)
        {
            if(JsonDocumentField == null) throw new ArgumentNullException(nameof(JsonDocumentField));
            if(JsonDocumentUtf8JsonField == null) throw new ArgumentNullException(nameof(JsonDocumentUtf8JsonField));
            var jsonDocument = JsonDocumentField.GetValue(jsonElement);
            Value = (ReadOnlyMemory<byte>) JsonDocumentUtf8JsonField.GetValue(jsonDocument);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T ToObject<T>(JsonSerializerOptions jsonSerializerOptions = null)
        {
            return (T) ToObject(typeof(T), jsonSerializerOptions);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public object ToObject([JetBrains.Annotations.NotNull] Type type, JsonSerializerOptions jsonSerializerOptions = null)
        {
            if (type == null) throw new ArgumentNullException(nameof(type));
            return JsonSerializer.Deserialize(Value.Span, type, jsonSerializerOptions);
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.