Пример #1
0
        /// <summary>
        /// Converts the <see cref="JsonNode"/> representing a single JSON value into a <typeparamref name="TValue"/>.
        /// </summary>
        /// <returns>A <typeparamref name="TValue"/> representation of the JSON value.</returns>
        /// <param name="node">The <see cref="JsonNode"/> to convert.</param>
        /// <param name="jsonTypeInfo">Metadata about the type to convert.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="jsonTypeInfo"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="JsonException">
        /// <typeparamref name="TValue" /> is not compatible with the JSON.
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// There is no compatible <see cref="System.Text.Json.Serialization.JsonConverter"/>
        /// for <typeparamref name="TValue"/> or its serializable members.
        /// </exception>
        public static TValue?Deserialize <TValue>(this JsonNode?node, JsonTypeInfo <TValue> jsonTypeInfo)
        {
            if (jsonTypeInfo == null)
            {
                throw new ArgumentNullException(nameof(jsonTypeInfo));
            }

            return(ReadUsingMetadata <TValue>(node, jsonTypeInfo));
        }
Пример #2
0
        /// <summary>
        /// Converts the <see cref="JsonNode"/> representing a single JSON value into a <typeparamref name="TValue"/>.
        /// </summary>
        /// <typeparam name="TValue">The type to deserialize the JSON value into.</typeparam>
        /// <returns>A <typeparamref name="TValue"/> representation of the JSON value.</returns>
        /// <param name="node">The <see cref="JsonNode"/> to convert.</param>
        /// <param name="jsonTypeInfo">Metadata about the type to convert.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="jsonTypeInfo"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="JsonException">
        /// <typeparamref name="TValue" /> is not compatible with the JSON.
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// There is no compatible <see cref="System.Text.Json.Serialization.JsonConverter"/>
        /// for <typeparamref name="TValue"/> or its serializable members.
        /// </exception>
        public static TValue?Deserialize <TValue>(this JsonNode?node, JsonTypeInfo <TValue> jsonTypeInfo)
        {
            if (jsonTypeInfo is null)
            {
                ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo));
            }

            return(ReadNode <TValue>(node, jsonTypeInfo));
        }
Пример #3
0
        internal override void GetPath(List <string> path, JsonNode?child)
        {
            Debug.Assert(child == null);

            if (Parent != null)
            {
                Parent.GetPath(path, this);
            }
        }
Пример #4
0
        public static object?Deserialize(this JsonNode?node, Type returnType, JsonSerializerOptions?options = null)
        {
            if (returnType == null)
            {
                throw new ArgumentNullException(nameof(returnType));
            }

            return(ReadUsingOptions <object?>(node, returnType, options));
        }
    public static bool DeepEquals(JsonNode?first, JsonNode?second)
    {
        if (ReferenceEquals(first, second))
        {
            return(true);
        }
        if (first is null && second is null)
        {
            return(true);
        }

        if (first is JsonValue firstValue && second is JsonValue secondValue)
        {
            return(DeepEquals(firstValue, secondValue));
        }

        if (first is JsonArray firstArray && second is JsonArray secondArray)
        {
            if (firstArray.Count != secondArray.Count)
            {
                return(false);
            }
            for (var i = 0; i < firstArray.Count; i++)
            {
                if (!DeepEquals(firstArray[i], secondArray[i]))
                {
                    return(false);
                }
            }

            return(true);
        }

        if (first is JsonObject firstObject && second is JsonObject secondObject)
        {
            if (firstObject.Count != secondObject.Count)
            {
                return(false);
            }
            foreach (var prop in firstObject)
            {
                if (!secondObject.TryGetPropertyValue(prop.Key, out var secondObjectValue))
                {
                    return(false);
                }
                if (!DeepEquals(prop.Value, secondObjectValue))
                {
                    return(false);
                }
            }

            return(true);
        }

        return(false);
    }
Пример #6
0
        private void DetachParent(JsonNode?item)
        {
            InitializeIfRequired();
            Debug.Assert(_dictionary != null);

            if (item != null)
            {
                item.Parent = null;
            }
        }
Пример #7
0
        internal override void GetPath(List <string> path, JsonNode?child)
        {
            if (child != null)
            {
                int index = List.IndexOf(child);
                path.Add($"[{index}]");
            }

            Parent?.GetPath(path, this);
        }
Пример #8
0
        private void DetachParent(JsonNode?item)
        {
            if (item != null)
            {
                item.Parent = null;
            }

            // Prevent previous child from being returned from these cached variables.
            ClearLastValueCache();
        }
Пример #9
0
        public static object?Deserialize(this JsonNode?node, Type returnType, JsonSerializerOptions?options = null)
        {
            if (returnType is null)
            {
                ThrowHelper.ThrowArgumentNullException(nameof(returnType));
            }

            JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, returnType);

            return(ReadNode <object?>(node, jsonTypeInfo));
        }
Пример #10
0
        internal void SetItem(string propertyName, JsonNode?value)
        {
            if (propertyName == null)
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            JsonNode?existing = SetNode(propertyName, value);

            DetachParent(existing);
        }
Пример #11
0
        internal void SetItem(string propertyName, JsonNode?value)
        {
            if (propertyName == null)
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            // Do a Remove+Add instead of SetItem to unparent existing value (if any).
            Remove(propertyName);
            Add(propertyName, value);
        }
Пример #12
0
        /// <summary>
        ///    Gets the <see cref="JsonNode"/> represented by the <paramref name="jsonElement"/>.
        ///    Operations performed on the returned <see cref="JsonNode"/> will modify the <paramref name="jsonElement"/>.
        ///    A return value indicates whether the operation succeeded.
        /// </summary>
        /// <param name="jsonElement"><see cref="JsonElement"/> to get the <see cref="JsonNode"/> from.</param>
        /// <param name="jsonNode"><see cref="JsonNode"/> represented by <paramref name="jsonElement"/>.</param>
        /// <returns>
        ///  <see langword="true"/> if the operation succeded;
        ///  otherwise, <see langword="false"/>
        /// </returns>
        public static bool TryGetNode(JsonElement jsonElement, [NotNullWhen(true)] out JsonNode?jsonNode)
        {
            if (!jsonElement.IsImmutable)
            {
                Debug.Assert(jsonElement._parent != null);
                jsonNode = (JsonNode)jsonElement._parent;
                return(true);
            }

            jsonNode = null;
            return(false);
        }
Пример #13
0
        /// <summary>
        /// Converts the <see cref="JsonNode"/> representing a single JSON value into a <paramref name="returnType"/>.
        /// </summary>
        /// <returns>A <paramref name="returnType"/> representation of the JSON value.</returns>
        /// <param name="node">The <see cref="JsonNode"/> to convert.</param>
        /// <param name="returnType">The type of the object to convert to and return.</param>
        /// <param name="context">A metadata provider for serializable types.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="returnType"/> is <see langword="null"/>.
        ///
        /// -or-
        ///
        /// <paramref name="context"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="JsonException">
        /// The JSON is invalid.
        ///
        /// -or-
        ///
        /// <paramref name="returnType" /> is not compatible with the JSON.
        ///
        /// -or-
        ///
        /// There is remaining data in the string beyond a single JSON value.</exception>
        /// <exception cref="NotSupportedException">
        /// There is no compatible <see cref="System.Text.Json.Serialization.JsonConverter"/>
        /// for <paramref name="returnType"/> or its serializable members.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// The <see cref="JsonSerializerContext.GetTypeInfo(Type)"/> method of the provided
        /// <paramref name="context"/> returns <see langword="null"/> for the type to convert.
        /// </exception>
        public static object?Deserialize(this JsonNode?node, Type returnType, JsonSerializerContext context)
        {
            if (returnType == null)
            {
                throw new ArgumentNullException(nameof(returnType));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            return(ReadUsingMetadata <object?>(node, GetTypeInfo(context, returnType)));
        }
Пример #14
0
        private void AddChild(JsonObject node, string propertyName, JsonElement element)
        {
            var options = new JsonNodeOptions
            {
                PropertyNameCaseInsensitive = Options.PropertyNameCaseInsensitive
            };

            JsonNode?childNode = element.ValueKind == JsonValueKind.Object
                ? JsonObject.Create(element, options)
                : element.ValueKind == JsonValueKind.Array
                    ? JsonArray.Create(element, options)
                    : JsonValue.Create(element, options);

            node[propertyName] = childNode;
        }
Пример #15
0
        private static void AddToParent(
            KeyValuePair <string?, JsonNode?> nodePair,
            ref Stack <KeyValuePair <string?, JsonNode?> > currentNodes,
            ref JsonNode?toReturn,
            DuplicatePropertyNameHandlingStrategy duplicatePropertyNameHandling = DuplicatePropertyNameHandlingStrategy.Replace)
        {
            if (currentNodes.TryPeek(out KeyValuePair <string?, JsonNode?> parentPair))
            {
                // Parent needs to be JsonObject or JsonArray
                Debug.Assert(parentPair.Value is JsonObject || parentPair.Value is JsonArray);

                if (parentPair.Value is JsonObject jsonObject)
                {
                    Debug.Assert(nodePair.Key != null);

                    // Handle duplicate properties accordingly to duplicatePropertyNameHandling:

                    if (duplicatePropertyNameHandling == DuplicatePropertyNameHandlingStrategy.Replace)
                    {
                        jsonObject[nodePair.Key] = nodePair.Value;
                    }
                    else if (jsonObject._dictionary.ContainsKey(nodePair.Key))
                    {
                        if (duplicatePropertyNameHandling == DuplicatePropertyNameHandlingStrategy.Error)
                        {
                            throw new ArgumentException(SR.JsonObjectDuplicateKey);
                        }

                        Debug.Assert(duplicatePropertyNameHandling == DuplicatePropertyNameHandlingStrategy.Ignore);
                    }
                    else
                    {
                        jsonObject.Add(nodePair !);
                    }
                }
                else if (parentPair.Value is JsonArray jsonArray)
                {
                    Debug.Assert(nodePair.Key == null);
                    jsonArray.Add(nodePair.Value);
                }
            }
            else
            {
                // We are at the top level, so adding node to parent means setting it as returned one

                toReturn = nodePair.Value;
            }
        }
Пример #16
0
        internal bool TrySetMemberCallback(SetMemberBinder binder, object?value)
        {
            JsonNode?node = null;

            if (value != null)
            {
                node = value as JsonNode;
                if (node == null)
                {
                    node = new JsonValue <object>(value, Options);
                }
            }

            Dictionary[binder.Name] = node;
            return(true);
        }
Пример #17
0
        private bool TrySetMemberCallback(SetMemberBinder binder, object?value)
        {
            JsonNode?node = null;

            if (value != null)
            {
                node = value as JsonNode;
                if (node == null)
                {
                    node = new JsonValueNotTrimmable <object>(value, Options);
                }
            }

            this[binder.Name] = node;
            return(true);
        }
Пример #18
0
        /// <summary>
        /// Converts the <see cref="JsonNode"/> representing a single JSON value into a <paramref name="returnType"/>.
        /// </summary>
        /// <returns>A <paramref name="returnType"/> representation of the JSON value.</returns>
        /// <param name="node">The <see cref="JsonNode"/> to convert.</param>
        /// <param name="returnType">The type of the object to convert to and return.</param>
        /// <param name="context">A metadata provider for serializable types.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="returnType"/> is <see langword="null"/>.
        ///
        /// -or-
        ///
        /// <paramref name="context"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="JsonException">
        /// The JSON is invalid.
        ///
        /// -or-
        ///
        /// <paramref name="returnType" /> is not compatible with the JSON.
        ///
        /// -or-
        ///
        /// There is remaining data in the string beyond a single JSON value.</exception>
        /// <exception cref="NotSupportedException">
        /// There is no compatible <see cref="System.Text.Json.Serialization.JsonConverter"/>
        /// for <paramref name="returnType"/> or its serializable members.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// The <see cref="JsonSerializerContext.GetTypeInfo(Type)"/> method of the provided
        /// <paramref name="context"/> returns <see langword="null"/> for the type to convert.
        /// </exception>
        public static object?Deserialize(this JsonNode?node, Type returnType, JsonSerializerContext context)
        {
            if (returnType == null)
            {
                throw new ArgumentNullException(nameof(returnType));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, returnType);

            return(ReadNode <object?>(node, jsonTypeInfo));
        }
Пример #19
0
        /// <summary>
        ///   Returns the value of a property with the specified name.
        /// </summary>
        /// <param name="propertyName">The name of the property to return.</param>
        /// <param name="jsonNode">The JSON value of the property with the specified name.</param>
        /// <returns>
        ///   <see langword="true"/> if a property with the specified name was found; otherwise, <see langword="false"/>.
        /// </returns>
        public bool TryGetPropertyValue(string propertyName, out JsonNode?jsonNode)
        {
            if (propertyName == _lastKey)
            {
                // Optimize for repeating sections in code:
                // obj.Foo.Bar.One
                // obj.Foo.Bar.Two
                jsonNode = _lastValue;
                return(true);
            }

            bool rc = Dictionary.TryGetValue(propertyName, out jsonNode);

            _lastKey   = propertyName;
            _lastValue = jsonNode;
            return(rc);
        }
Пример #20
0
        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    Source?.Dispose();
                    _document = null;
                    _jsonNode = null;
                    Source    = null;
                }

                // TODO: free unmanaged resources (unmanaged objects) and override finalizer
                // TODO: set large fields to null
                disposedValue = true;
            }
        }
Пример #21
0
 protected virtual void Visit(JsonArray arr, JsonVariableVisitorContext context)
 {
     for (var i = 0; i < arr.Count; i++)
     {
         JsonNode?element = arr[i];
         if (element is not null)
         {
             var index = i;
             context.SetValue.Push(value =>
             {
                 arr[index] = value;
             });
             Visit(element, context);
             context.SetValue.Pop();
         }
     }
 }
Пример #22
0
        internal override void ReadElementAndSetProperty(
            object obj,
            string propertyName,
            ref Utf8JsonReader reader,
            JsonSerializerOptions options,
            ref ReadStack state)
        {
            bool success = JsonNodeConverter.Instance.TryRead(ref reader, typeof(JsonNode), options, ref state, out JsonNode? value);
            Debug.Assert(success); // Node converters are not resumable.

            Debug.Assert(obj is JsonObject);
            JsonObject jObject = (JsonObject)obj;

            Debug.Assert(value == null || value is JsonNode);
            JsonNode? jNodeValue = (JsonNode?)value;

            jObject[propertyName] = jNodeValue;
        }
Пример #23
0
        public void Add <[DynamicallyAccessedMembers(JsonHelpers.MembersAccessedOnRead)] T>(T?value)
        {
            if (value == null)
            {
                Add(null);
            }
            else
            {
                JsonNode?jNode = value as JsonNode;
                if (jNode == null)
                {
                    jNode = new JsonValueNotTrimmable <T>(value);
                }

                // Call the IList.Add() implementation.
                Add(jNode);
            }
        }
Пример #24
0
        public void Add <T>(T?value)
        {
            if (value == null)
            {
                Add(null);
            }
            else
            {
                JsonNode?jNode = value as JsonNode;
                if (jNode == null)
                {
                    jNode = new JsonValueNotTrimmable <T>(value);
                }

                // Call the IList.Add() implementation.
                Add(jNode);
            }
        }
Пример #25
0
        internal override void GetPath(List <string> path, JsonNode?child)
        {
            if (child != null)
            {
                InitializeIfRequired();
                Debug.Assert(_dictionary != null);
                string propertyName = _dictionary.FindValue(child) !.Value.Key;
                if (propertyName.IndexOfAny(ReadStack.SpecialCharacters) != -1)
                {
                    path.Add($"['{propertyName}']");
                }
                else
                {
                    path.Add($".{propertyName}");
                }
            }

            Parent?.GetPath(path, this);
        }
Пример #26
0
        internal override void GetPath(List <string> path, JsonNode?child)
        {
            if (child != null)
            {
                string propertyName = FindNode(child) !.Value.Key;
                if (propertyName.IndexOfAny(ReadStack.SpecialCharacters) != -1)
                {
                    path.Add($"['{propertyName}']");
                }
                else
                {
                    path.Add($".{propertyName}");
                }
            }

            if (Parent != null)
            {
                Parent.GetPath(path, this);
            }
        }
Пример #27
0
        private static TValue?ReadNode <TValue>(JsonNode?node, JsonTypeInfo jsonTypeInfo)
        {
            JsonSerializerOptions options = jsonTypeInfo.Options;

            // For performance, share the same buffer across serialization and deserialization.
            using var output = new PooledByteBufferWriter(options.DefaultBufferSize);
            using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions()))
            {
                if (node is null)
                {
                    writer.WriteNullValue();
                }
                else
                {
                    node.WriteTo(writer, options);
                }
            }

            return(ReadFromSpan <TValue>(output.WrittenMemory.Span, jsonTypeInfo));
        }
Пример #28
0
        internal void AssignParent(JsonNode parent)
        {
            if (Parent != null)
            {
                ThrowHelper.ThrowInvalidOperationException_NodeAlreadyHasParent();
            }

            JsonNode?p = parent;

            while (p != null)
            {
                if (p == this)
                {
                    ThrowHelper.ThrowInvalidOperationException_NodeCycleDetected();
                }

                p = p.Parent;
            }

            Parent = parent;
        }
                    static string ReadAsStringMetadataValue(JsonNode?jsonNode)
                    {
                        if (jsonNode is JsonValue jsonValue &&
                            jsonValue.TryGetValue(out string?value) &&
                            value is not null)
                        {
                            return(value);
                        }

                        JsonValueKind metadataValueKind = jsonNode switch
                        {
                            null => JsonValueKind.Null,
                            JsonObject => JsonValueKind.Object,
                            JsonArray => JsonValueKind.Array,
                            JsonValue <JsonElement> element => element.Value.ValueKind,
                            _ => JsonValueKind.Undefined,
                        };

                        Debug.Assert(metadataValueKind != JsonValueKind.Undefined);
                        ThrowHelper.ThrowJsonException_MetadataValueWasNotString(metadataValueKind);
                        return(null !);
                    }
Пример #30
0
 public override void Write(Utf8JsonWriter writer, JsonNode?value, JsonSerializerOptions options)
 {
     if (value == null)
     {
         writer.WriteNullValue();
         // Note JsonSerializer.Deserialize<T>(JsonNode?) also calls WriteNullValue() for a null + root JsonNode.
     }
     else
     {
         if (value is JsonValue jsonValue)
         {
             ValueConverter.Write(writer, jsonValue, options);
         }
         else if (value is JsonObject jsonObject)
         {
             ObjectConverter.Write(writer, jsonObject, options);
         }
         else
         {
             Debug.Assert(value is JsonArray);
             ArrayConverter.Write(writer, (JsonArray)value, options);
         }
     }
 }