Closed pranavkm closed 4 years ago
cc @ahsonkhan \ @JeremyKuhne \ @steveharter
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 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);
}
}
}
It makes sense to add a method to JsonElement
to get a raw value. Shouldn't be hard because JsonDocument
already has it:
public readonly struct JsonElement
{
public ReadOnlyMemory<byte> GetRawValue()
{
CheckValidInstance();
return _parent.GetRawValue(_idx, includeQuotes: true);
}
}
@YohDeadfall We're intentionally not adding that method. JsonElement
doesn't say Utf8
anywhere in the name, and we consider it to be encoding-agnostic. (JsonDocument can be built from a string
, the fact that it transcodes is currently considered an implementation detail).
JsonElement.GetRawText
is the compromise, it gives the input, but as a string
. When Utf8String comes in, there'll be a Utf8String version.
Closing as duplicate of https://github.com/dotnet/corefx/issues/42056. The semantics of this feature are covered in the API proposal:
namespace System.Text.Json
{
public static partial class JsonSerializer
{
public static TValue Deserialize<TValue>(this JsonDocument document);
public static TValue Deserialize<TValue>(this JsonElement element);
public static JsonDocument SerializeToDocument<TValue>(TValue value);
}
}
Probably the same as this - https://github.com/dotnet/corefx/issues/36169, but better worded. It would be useful to have an API that allows deserializing
JsonElement
in to "T" e.g.Right now the only way to do this is to get to the raw text of the element which just results in needless allocations: