File: System\Text\Json\Nodes\JsonValueOfTCustomized.cs
Web Access
Project: src\src\libraries\System.Text.Json\src\System.Text.Json.csproj (System.Text.Json)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Text.Json.Serialization.Metadata;
 
namespace System.Text.Json.Nodes
{
    /// <summary>
    /// A JsonValue that encapsulates arbitrary .NET type configurations.
    /// Paradoxically, instances of this type can be of any JsonValueKind
    /// (including objects and arrays) and introspecting these values is
    /// generally slower compared to the other JsonValue implementations.
    /// </summary>
    internal sealed class JsonValueCustomized<TValue> : JsonValue<TValue>
    {
        private readonly JsonTypeInfo<TValue> _jsonTypeInfo;
        private JsonValueKind? _valueKind;
 
        public JsonValueCustomized(TValue value, JsonTypeInfo<TValue> jsonTypeInfo, JsonNodeOptions? options = null): base(value, options)
        {
            Debug.Assert(jsonTypeInfo.IsConfigured);
            _jsonTypeInfo = jsonTypeInfo;
        }
 
        private protected override JsonValueKind GetValueKindCore() => _valueKind ??= ComputeValueKind();
        internal override JsonNode DeepCloneCore() => JsonSerializer.SerializeToNode(Value, _jsonTypeInfo)!;
 
        public override void WriteTo(Utf8JsonWriter writer, JsonSerializerOptions? options = null)
        {
            if (writer is null)
            {
                ThrowHelper.ThrowArgumentNullException(nameof(writer));
            }
 
            JsonTypeInfo<TValue> jsonTypeInfo = _jsonTypeInfo;
 
            if (options != null && options != jsonTypeInfo.Options)
            {
                options.MakeReadOnly();
                jsonTypeInfo = (JsonTypeInfo<TValue>)options.GetTypeInfoInternal(typeof(TValue));
            }
 
            jsonTypeInfo.Serialize(writer, Value);
        }
 
        /// <summary>
        /// Computes the JsonValueKind of the value by serializing it and reading the resultant JSON.
        /// </summary>
        private JsonValueKind ComputeValueKind()
        {
            Utf8JsonWriter writer = Utf8JsonWriterCache.RentWriterAndBuffer(options: default, JsonSerializerOptions.BufferSizeDefault, out PooledByteBufferWriter output);
            try
            {
                WriteTo(writer);
                writer.Flush();
                Utf8JsonReader reader = new(output.WrittenMemory.Span);
                bool success = reader.Read();
                Debug.Assert(success);
                return JsonReaderHelper.ToValueKind(reader.TokenType);
            }
            finally
            {
                Utf8JsonWriterCache.ReturnWriterAndBuffer(writer, output);
            }
        }
    }
}