< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 288
Coverable lines: 288
Total lines: 787
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 102
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
File 1: .ctor(...)100%110%
File 1: .ctor(...)0%660%
File 1: Create(...)0%440%
File 1: .ctor(...)100%110%
File 1: GetItem(...)100%110%
File 1: SetItem(...)100%110%
File 1: DeepCloneCore()0%880%
File 1: GetPropertyName(...)0%220%
File 1: TryGetPropertyValue(...)100%110%
File 1: TryGetPropertyValue(...)100%110%
File 1: WriteTo(...)0%440%
File 1: WriteContentsTo(...)0%10100%
File 1: GetValueKindCore()100%110%
File 1: DeepEqualsCore(...)0%14140%
File 1: GetItem(...)0%220%
File 1: GetPath(...)0%660%
File 1: SetItem(...)0%660%
File 1: DetachParent(...)0%220%
File 1: FindValue(...)0%440%
File 2: Add(...)0%220%
File 2: TryAdd(...)100%110%
File 2: TryAdd(...)0%440%
File 2: Add(...)100%110%
File 2: Clear()0%440%
File 2: ContainsKey(...)100%110%
File 2: Remove(...)0%220%
File 2: System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.Contains(...)100%110%
File 2: System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.CopyTo(...)100%110%
File 2: GetEnumerator()100%110%
File 2: System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.Remove(...)100%110%
File 2: System.Collections.Generic.IDictionary<System.String,System.Text.Json.Nodes.JsonNode>.TryGetValue(...)100%110%
File 2: System.Collections.IEnumerable.GetEnumerator()100%110%
File 2: InitializeDictionary()0%10100%
File 2: CreateDictionary(...)0%440%
File 2: GetUnderlyingRepresentation(...)100%110%
File 3: GetAt(...)100%110%
File 3: SetAt(...)0%220%
File 3: SetAt(...)0%220%
File 3: IndexOf(...)100%110%
File 3: Insert(...)0%220%
File 3: RemoveAt(...)100%110%
File 3: System.Collections.Generic.IList<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.IndexOf(...)100%110%
File 3: System.Collections.Generic.IList<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.Insert(...)100%110%
File 3: System.Collections.Generic.IList<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.RemoveAt(...)100%110%

File(s)

D:\runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Nodes\JsonObject.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections.Generic;
 5using System.Diagnostics;
 6using System.Diagnostics.CodeAnalysis;
 7
 8namespace System.Text.Json.Nodes
 9{
 10    /// <summary>
 11    ///   Represents a mutable JSON object.
 12    /// </summary>
 13    /// <remarks>
 14    /// It's safe to perform multiple concurrent read operations on a <see cref="JsonObject"/>,
 15    /// but issues can occur if the collection is modified while it's being read.
 16    /// </remarks>
 17    [DebuggerDisplay("JsonObject[{Count}]")]
 18    [DebuggerTypeProxy(typeof(DebugView))]
 19    public sealed partial class JsonObject : JsonNode
 20    {
 21        private JsonElement? _jsonElement;
 22
 023        internal override JsonElement? UnderlyingElement => _jsonElement;
 24
 25        /// <summary>
 26        ///   Initializes a new instance of the <see cref="JsonObject"/> class that is empty.
 27        /// </summary>
 28        /// <param name="options">Options to control the behavior.</param>
 029        public JsonObject(JsonNodeOptions? options = null) : base(options) { }
 30
 31        /// <summary>
 32        ///   Initializes a new instance of the <see cref="JsonObject"/> class that contains the specified <paramref nam
 33        /// </summary>
 34        /// <param name="properties">The properties to be added.</param>
 35        /// <param name="options">Options to control the behavior.</param>
 036        public JsonObject(IEnumerable<KeyValuePair<string, JsonNode?>> properties, JsonNodeOptions? options = null) : th
 037        {
 038            int capacity = properties is ICollection<KeyValuePair<string, JsonNode?>> propertiesCollection ? propertiesC
 039            OrderedDictionary<string, JsonNode?> dictionary = CreateDictionary(options, capacity);
 40
 041            foreach (KeyValuePair<string, JsonNode?> node in properties)
 042            {
 043                dictionary.Add(node.Key, node.Value);
 044                node.Value?.AssignParent(this);
 045            }
 46
 047            _dictionary = dictionary;
 048        }
 49
 50        /// <summary>
 51        ///   Initializes a new instance of the <see cref="JsonObject"/> class that contains properties from the specifi
 52        /// </summary>
 53        /// <returns>
 54        ///   The new instance of the <see cref="JsonObject"/> class that contains properties from the specified <see cr
 55        /// </returns>
 56        /// <param name="element">The <see cref="JsonElement"/>.</param>
 57        /// <param name="options">Options to control the behavior.</param>
 58        /// <returns>A <see cref="JsonObject"/>.</returns>
 59        public static JsonObject? Create(JsonElement element, JsonNodeOptions? options = null)
 060        {
 061            return element.ValueKind switch
 062            {
 063                JsonValueKind.Null => null,
 064                JsonValueKind.Object => new JsonObject(element, options),
 065                _ => throw new InvalidOperationException(SR.Format(SR.NodeElementWrongType, nameof(JsonValueKind.Object)
 066            };
 067        }
 68
 069        internal JsonObject(JsonElement element, JsonNodeOptions? options = null) : this(options)
 070        {
 071            Debug.Assert(element.ValueKind == JsonValueKind.Object);
 072            _jsonElement = element;
 073        }
 74
 75        /// <summary>
 76        /// Gets or creates the underlying dictionary containing the properties of the object.
 77        /// </summary>
 078        private OrderedDictionary<string, JsonNode?> Dictionary => _dictionary ?? InitializeDictionary();
 79
 080        private protected override JsonNode? GetItem(int index) => GetAt(index).Value;
 081        private protected override void SetItem(int index, JsonNode? value) => SetAt(index, value);
 82
 83        internal override JsonNode DeepCloneCore()
 084        {
 085            GetUnderlyingRepresentation(out OrderedDictionary<string, JsonNode?>? dictionary, out JsonElement? jsonEleme
 86
 087            if (dictionary is null)
 088            {
 089                return jsonElement.HasValue
 090                    ? new JsonObject(jsonElement.Value.Clone(), Options)
 091                    : new JsonObject(Options);
 92            }
 93
 094            var jObject = new JsonObject(Options)
 095            {
 096                _dictionary = CreateDictionary(Options, Count)
 097            };
 98
 099            foreach (KeyValuePair<string, JsonNode?> item in dictionary)
 0100            {
 0101                jObject.Add(item.Key, item.Value?.DeepCloneCore());
 0102            }
 103
 0104            return jObject;
 0105        }
 106
 107        internal string GetPropertyName(JsonNode? node)
 0108        {
 0109            KeyValuePair<string, JsonNode?>? item = FindValue(node);
 0110            return item.HasValue ? item.Value.Key : string.Empty;
 0111        }
 112
 113        /// <summary>
 114        ///   Returns the value of a property with the specified name.
 115        /// </summary>
 116        /// <param name="propertyName">The name of the property to return.</param>
 117        /// <param name="jsonNode">The JSON value of the property with the specified name.</param>
 118        /// <exception cref="ArgumentNullException">
 119        ///   <paramref name="propertyName"/> is <see langword="null"/>.
 120        /// </exception>
 121        /// <returns>
 122        ///   <see langword="true"/> if a property with the specified name was found; otherwise, <see langword="false"/>
 123        /// </returns>
 0124        public bool TryGetPropertyValue(string propertyName, out JsonNode? jsonNode) => TryGetPropertyValue(propertyName
 125
 126        /// <summary>
 127        ///   Gets the value associated with the specified property name.
 128        /// </summary>
 129        /// <param name="propertyName">The property name of the value to get.</param>
 130        /// <param name="jsonNode">
 131        ///   When this method returns, it contains the value associated with the specified property name, if the proper
 132        ///   otherwise <see langword="null"/>.
 133        /// </param>
 134        /// <param name="index">The index of <paramref name="propertyName"/> if found; otherwise, -1.</param>
 135        /// <exception cref="ArgumentNullException">
 136        ///   <paramref name="propertyName"/> is <see langword="null"/>.
 137        /// </exception>
 138        /// <returns>
 139        ///   <see langword="true"/> if the <see cref="JsonObject"/> contains an element with the specified property nam
 140        /// </returns>
 141        public bool TryGetPropertyValue(string propertyName, out JsonNode? jsonNode, out int index)
 0142        {
 0143            ArgumentNullException.ThrowIfNull(propertyName);
 144
 0145            return Dictionary.TryGetValue(propertyName, out jsonNode, out index);
 0146        }
 147
 148        /// <inheritdoc/>
 149        public override void WriteTo(Utf8JsonWriter writer, JsonSerializerOptions? options = null)
 0150        {
 0151            ArgumentNullException.ThrowIfNull(writer);
 152
 0153            GetUnderlyingRepresentation(out OrderedDictionary<string, JsonNode?>? dictionary, out JsonElement? jsonEleme
 154
 0155            if (dictionary is null && jsonElement.HasValue)
 0156            {
 157                // Write the element without converting to nodes.
 0158                jsonElement.Value.WriteTo(writer);
 0159            }
 160            else
 0161            {
 0162                writer.WriteStartObject();
 0163                WriteContentsTo(writer, options);
 0164                writer.WriteEndObject();
 0165            }
 0166        }
 167
 168        /// <summary>
 169        /// Writes the properties of this JsonObject to the writer without the surrounding braces.
 170        /// This is used for extension data serialization where the properties should be flattened
 171        /// into the parent object.
 172        /// </summary>
 173        internal void WriteContentsTo(Utf8JsonWriter writer, JsonSerializerOptions? options)
 0174        {
 0175            GetUnderlyingRepresentation(out OrderedDictionary<string, JsonNode?>? dictionary, out JsonElement? jsonEleme
 176
 0177            if (dictionary is null && jsonElement.HasValue)
 0178            {
 179                // Write properties from the underlying JsonElement without converting to nodes.
 0180                foreach (JsonProperty property in jsonElement.Value.EnumerateObject())
 0181                {
 0182                    property.WriteTo(writer);
 0183                }
 0184            }
 185            else
 0186            {
 0187                foreach (KeyValuePair<string, JsonNode?> entry in Dictionary)
 0188                {
 0189                    writer.WritePropertyName(entry.Key);
 190
 0191                    if (entry.Value is null)
 0192                    {
 0193                        writer.WriteNullValue();
 0194                    }
 195                    else
 0196                    {
 0197                        entry.Value.WriteTo(writer, options);
 0198                    }
 0199                }
 0200            }
 0201        }
 202
 0203        private protected override JsonValueKind GetValueKindCore() => JsonValueKind.Object;
 204
 205        internal override bool DeepEqualsCore(JsonNode node)
 0206        {
 0207            switch (node)
 208            {
 209                case JsonArray:
 0210                    return false;
 211                case JsonValue value:
 212                    // JsonValue instances have special comparison semantics, dispatch to their implementation.
 0213                    return value.DeepEqualsCore(this);
 214                case JsonObject jsonObject:
 0215                    OrderedDictionary<string, JsonNode?> currentDict = Dictionary;
 0216                    OrderedDictionary<string, JsonNode?> otherDict = jsonObject.Dictionary;
 217
 0218                    if (currentDict.Count != otherDict.Count)
 0219                    {
 0220                        return false;
 221                    }
 222
 0223                    foreach (KeyValuePair<string, JsonNode?> item in currentDict)
 0224                    {
 0225                        if (!otherDict.TryGetValue(item.Key, out JsonNode? jsonNode) || !DeepEquals(item.Value, jsonNode
 0226                        {
 0227                            return false;
 228                        }
 0229                    }
 230
 0231                    return true;
 232                default:
 0233                    Debug.Fail("Impossible case");
 234                    return false;
 235            }
 0236        }
 237
 238        internal JsonNode? GetItem(string propertyName)
 0239        {
 0240            ArgumentNullException.ThrowIfNull(propertyName);
 241
 0242            if (TryGetPropertyValue(propertyName, out JsonNode? value))
 0243            {
 0244                return value;
 245            }
 246
 247            // Return null for missing properties.
 0248            return null;
 0249        }
 250
 251        internal override void GetPath(ref ValueStringBuilder path, JsonNode? child)
 0252        {
 0253            Parent?.GetPath(ref path, this);
 254
 0255            if (child is not null)
 0256            {
 0257                string propertyName = FindValue(child)!.Value.Key;
 0258                if (propertyName.AsSpan().ContainsSpecialCharacters())
 0259                {
 0260                    path.Append("['");
 0261                    path.AppendEscapedPropertyName(propertyName);
 0262                    path.Append("']");
 0263                }
 264                else
 0265                {
 0266                    path.Append('.');
 0267                    path.Append(propertyName);
 0268                }
 0269            }
 0270        }
 271
 272        internal void SetItem(string propertyName, JsonNode? value)
 0273        {
 0274            ArgumentNullException.ThrowIfNull(propertyName);
 275
 0276            OrderedDictionary<string, JsonNode?> dict = Dictionary;
 277
 0278            if (!dict.TryAdd(propertyName, value, out int index))
 0279            {
 0280                Debug.Assert(index >= 0);
 0281                JsonNode? replacedValue = dict.GetAt(index).Value;
 282
 0283                if (ReferenceEquals(value, replacedValue))
 0284                {
 0285                    return;
 286                }
 287
 0288                DetachParent(replacedValue);
 0289                dict.SetAt(index, value);
 0290            }
 291
 0292            value?.AssignParent(this);
 0293        }
 294
 295        private void DetachParent(JsonNode? item)
 0296        {
 0297            Debug.Assert(_dictionary is not null, "Cannot have detachable nodes without a materialized dictionary.");
 298
 0299            item?.Parent = null;
 0300        }
 301
 302        private KeyValuePair<string, JsonNode?>? FindValue(JsonNode? value)
 0303        {
 0304            foreach (KeyValuePair<string, JsonNode?> item in Dictionary)
 0305            {
 0306                if (ReferenceEquals(item.Value, value))
 0307                {
 0308                    return item;
 309                }
 0310            }
 311
 0312            return null;
 0313        }
 314
 315        [ExcludeFromCodeCoverage] // Justification = "Design-time"
 316        private sealed class DebugView
 317        {
 318            [DebuggerBrowsable(DebuggerBrowsableState.Never)]
 319            private readonly JsonObject _node;
 320
 321            public DebugView(JsonObject node)
 322            {
 323                _node = node;
 324            }
 325
 326            public string Json => _node.ToJsonString();
 327            public string Path => _node.GetPath();
 328
 329            [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
 330            private DebugViewProperty[] Items
 331            {
 332                get
 333                {
 334                    DebugViewProperty[] properties = new DebugViewProperty[_node.Count];
 335
 336                    int i = 0;
 337                    foreach (KeyValuePair<string, JsonNode?> item in _node)
 338                    {
 339                        properties[i].PropertyName = item.Key;
 340                        properties[i].Value = item.Value;
 341                        i++;
 342                    }
 343
 344                    return properties;
 345                }
 346            }
 347
 348            [DebuggerDisplay("{Display,nq}")]
 349            private struct DebugViewProperty
 350            {
 351                [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
 352                public JsonNode? Value;
 353
 354                [DebuggerBrowsable(DebuggerBrowsableState.Never)]
 355                public string PropertyName;
 356
 357                [DebuggerBrowsable(DebuggerBrowsableState.Never)]
 358                public string Display
 359                {
 360                    get
 361                    {
 362                        if (Value is null)
 363                        {
 364                            return $"{PropertyName} = null";
 365                        }
 366
 367                        if (Value is JsonValue)
 368                        {
 369                            return $"{PropertyName} = {Value.ToJsonString()}";
 370                        }
 371
 372                        if (Value is JsonObject jsonObject)
 373                        {
 374                            return $"{PropertyName} = JsonObject[{jsonObject.Count}]";
 375                        }
 376
 377                        JsonArray jsonArray = (JsonArray)Value;
 378                        return $"{PropertyName} = JsonArray[{jsonArray.Count}]";
 379                    }
 380                }
 381
 382            }
 383        }
 384    }
 385}

D:\runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Nodes\JsonObject.IDictionary.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections;
 5using System.Collections.Generic;
 6using System.Text.Json.Serialization.Converters;
 7using System.Threading;
 8
 9namespace System.Text.Json.Nodes
 10{
 11    public partial class JsonObject : IDictionary<string, JsonNode?>
 12    {
 13        private OrderedDictionary<string, JsonNode?>? _dictionary;
 14
 15        /// <summary>
 16        ///   Adds an element with the provided property name and value to the <see cref="JsonObject"/>.
 17        /// </summary>
 18        /// <param name="propertyName">The property name of the element to add.</param>
 19        /// <param name="value">The value of the element to add.</param>
 20        /// <exception cref="ArgumentNullException">
 21        ///   <paramref name="propertyName"/>is <see langword="null"/>.
 22        /// </exception>
 23        /// <exception cref="ArgumentException">
 24        ///   An element with the same property name already exists in the <see cref="JsonObject"/>.
 25        /// </exception>
 26        public void Add(string propertyName, JsonNode? value)
 027        {
 028            ArgumentNullException.ThrowIfNull(propertyName);
 29
 030            Dictionary.Add(propertyName, value);
 031            value?.AssignParent(this);
 032        }
 33
 34        /// <summary>
 35        ///   Adds an element with the provided name and value to the <see cref="JsonObject"/>, if a property named <par
 36        /// </summary>
 37        /// <param name="propertyName">The property name of the element to add.</param>
 38        /// <param name="value">The value of the element to add.</param>
 39        /// <exception cref="ArgumentNullException"><paramref name="propertyName"/> is null.</exception>
 40        /// <returns>
 41        ///   <see langword="true"/> if the property didn't exist and the element was added; otherwise, <see langword="f
 42        /// </returns>
 043        public bool TryAdd(string propertyName, JsonNode? value) => TryAdd(propertyName, value, out _);
 44
 45        /// <summary>
 46        ///   Adds an element with the provided name and value to the <see cref="JsonObject"/>, if a property named <par
 47        /// </summary>
 48        /// <param name="propertyName">The property name of the element to add.</param>
 49        /// <param name="value">The value of the element to add.</param>
 50        /// <param name="index">The index of the added or existing <paramref name="propertyName"/>. This is always a val
 51        /// <exception cref="ArgumentNullException"><paramref name="propertyName"/> is null.</exception>
 52        /// <returns>
 53        ///   <see langword="true"/> if the property didn't exist and the element was added; otherwise, <see langword="f
 54        /// </returns>
 55        public bool TryAdd(string propertyName, JsonNode? value, out int index)
 056        {
 057            ArgumentNullException.ThrowIfNull(propertyName);
 58
 059            bool success = Dictionary.TryAdd(propertyName, value, out index);
 060            if (success)
 061            {
 062                value?.AssignParent(this);
 063            }
 064            return success;
 065        }
 66
 67        /// <summary>
 68        ///   Adds the specified property to the <see cref="JsonObject"/>.
 69        /// </summary>
 70        /// <param name="property">
 71        ///   The KeyValuePair structure representing the property name and value to add to the <see cref="JsonObject"/>
 72        /// </param>
 73        /// <exception cref="ArgumentException">
 74        ///   An element with the same property name already exists in the <see cref="JsonObject"/>.
 75        /// </exception>
 76        /// <exception cref="ArgumentNullException">
 77        ///   The property name of <paramref name="property"/> is <see langword="null"/>.
 78        /// </exception>
 079        public void Add(KeyValuePair<string, JsonNode?> property) => Add(property.Key, property.Value);
 80
 81        /// <summary>
 82        ///   Removes all elements from the <see cref="JsonObject"/>.
 83        /// </summary>
 84        public void Clear()
 085        {
 086            OrderedDictionary<string, JsonNode?>? dictionary = _dictionary;
 87
 088            if (dictionary is null)
 089            {
 090                _jsonElement = null;
 091                return;
 92            }
 93
 094            foreach (JsonNode? node in dictionary.Values)
 095            {
 096                DetachParent(node);
 097            }
 98
 099            dictionary.Clear();
 0100        }
 101
 102        /// <summary>
 103        ///   Determines whether the <see cref="JsonObject"/> contains an element with the specified property name.
 104        /// </summary>
 105        /// <param name="propertyName">The property name to locate in the <see cref="JsonObject"/>.</param>
 106        /// <returns>
 107        ///   <see langword="true"/> if the <see cref="JsonObject"/> contains an element with the specified property nam
 108        /// </returns>
 109        /// <exception cref="ArgumentNullException">
 110        ///   <paramref name="propertyName"/> is <see langword="null"/>.
 111        /// </exception>
 112        public bool ContainsKey(string propertyName)
 0113        {
 0114            ArgumentNullException.ThrowIfNull(propertyName);
 115
 0116            return Dictionary.ContainsKey(propertyName);
 0117        }
 118
 119        /// <summary>
 120        ///   Gets the number of elements contained in <see cref="JsonObject"/>.
 121        /// </summary>
 0122        public int Count => Dictionary.Count;
 123
 124        /// <summary>
 125        ///   Removes the element with the specified property name from the <see cref="JsonObject"/>.
 126        /// </summary>
 127        /// <param name="propertyName">The property name of the element to remove.</param>
 128        /// <returns>
 129        ///   <see langword="true"/> if the element is successfully removed; otherwise, <see langword="false"/>.
 130        /// </returns>
 131        /// <exception cref="ArgumentNullException">
 132        ///   <paramref name="propertyName"/> is <see langword="null"/>.
 133        /// </exception>
 134        public bool Remove(string propertyName)
 0135        {
 0136            ArgumentNullException.ThrowIfNull(propertyName);
 137
 0138            bool success = Dictionary.Remove(propertyName, out JsonNode? removedNode);
 0139            if (success)
 0140            {
 0141                DetachParent(removedNode);
 0142            }
 143
 0144            return success;
 0145        }
 146
 147        /// <summary>
 148        ///   Determines whether the <see cref="JsonObject"/> contains a specific property name and <see cref="JsonNode"
 149        /// </summary>
 150        /// <param name="item">The element to locate in the <see cref="JsonObject"/>.</param>
 151        /// <returns>
 152        ///   <see langword="true"/> if the <see cref="JsonObject"/> contains an element with the property name; otherwi
 153        /// </returns>
 154        bool ICollection<KeyValuePair<string, JsonNode?>>.Contains(KeyValuePair<string, JsonNode?> item) =>
 0155            ((IDictionary<string, JsonNode?>)Dictionary).Contains(item);
 156
 157        /// <summary>
 158        ///   Copies the elements of the <see cref="JsonObject"/> to an array of type KeyValuePair starting at the speci
 159        /// </summary>
 160        /// <param name="array">
 161        ///   The one-dimensional Array that is the destination of the elements copied from <see cref="JsonObject"/>.
 162        /// </param>
 163        /// <param name="index">The zero-based index in <paramref name="array"/> at which copying begins.</param>
 164        /// <exception cref="ArgumentNullException">
 165        ///   <paramref name="array"/> is <see langword="null"/>.
 166        /// </exception>
 167        /// <exception cref="ArgumentOutOfRangeException">
 168        ///   <paramref name="index"/> is less than 0.
 169        /// </exception>
 170        /// <exception cref="ArgumentException">
 171        ///   The number of elements in the source ICollection is greater than the available space from <paramref name="
 172        ///   to the end of the destination <paramref name="array"/>.
 173        /// </exception>
 174        void ICollection<KeyValuePair<string, JsonNode?>>.CopyTo(KeyValuePair<string, JsonNode?>[] array, int index) =>
 0175            ((IDictionary<string, JsonNode?>)Dictionary).CopyTo(array, index);
 176
 177        /// <summary>
 178        ///   Returns an enumerator that iterates through the <see cref="JsonObject"/>.
 179        /// </summary>
 180        /// <returns>
 181        ///   An enumerator that iterates through the <see cref="JsonObject"/>.
 182        /// </returns>
 0183        public IEnumerator<KeyValuePair<string, JsonNode?>> GetEnumerator() => Dictionary.GetEnumerator();
 184
 185        /// <summary>
 186        ///   Removes a key and value from the <see cref="JsonObject"/>.
 187        /// </summary>
 188        /// <param name="item">
 189        ///   The KeyValuePair structure representing the property name and value to remove from the <see cref="JsonObje
 190        /// </param>
 191        /// <returns>
 192        ///   <see langword="true"/> if the element is successfully removed; otherwise, <see langword="false"/>.
 193        /// </returns>
 0194        bool ICollection<KeyValuePair<string, JsonNode?>>.Remove(KeyValuePair<string, JsonNode?> item) => Remove(item.Ke
 195
 196        /// <summary>
 197        ///   Gets a collection containing the property names in the <see cref="JsonObject"/>.
 198        /// </summary>
 0199        ICollection<string> IDictionary<string, JsonNode?>.Keys => Dictionary.Keys;
 200
 201        /// <summary>
 202        ///   Gets a collection containing the property values in the <see cref="JsonObject"/>.
 203        /// </summary>
 0204        ICollection<JsonNode?> IDictionary<string, JsonNode?>.Values => Dictionary.Values;
 205
 206        /// <summary>
 207        ///   Gets the value associated with the specified property name.
 208        /// </summary>
 209        /// <param name="propertyName">The property name of the value to get.</param>
 210        /// <param name="jsonNode">
 211        ///   When this method returns, contains the value associated with the specified property name, if the property 
 212        ///   otherwise, <see langword="null"/>.
 213        /// </param>
 214        /// <returns>
 215        ///   <see langword="true"/> if the <see cref="JsonObject"/> contains an element with the specified property nam
 216        /// </returns>
 217        /// <exception cref="ArgumentNullException">
 218        ///   <paramref name="propertyName"/> is <see langword="null"/>.
 219        /// </exception>
 220        bool IDictionary<string, JsonNode?>.TryGetValue(string propertyName, out JsonNode? jsonNode)
 0221        {
 0222            ArgumentNullException.ThrowIfNull(propertyName);
 223
 0224            return Dictionary.TryGetValue(propertyName, out jsonNode);
 0225        }
 226
 227        /// <summary>
 228        ///   Returns <see langword="false"/>.
 229        /// </summary>
 0230        bool ICollection<KeyValuePair<string, JsonNode?>>.IsReadOnly => false;
 231
 232        /// <summary>
 233        ///   Returns an enumerator that iterates through the <see cref="JsonObject"/>.
 234        /// </summary>
 235        /// <returns>
 236        ///   An enumerator that iterates through the <see cref="JsonObject"/>.
 237        /// </returns>
 0238        IEnumerator IEnumerable.GetEnumerator() => Dictionary.GetEnumerator();
 239
 240        private OrderedDictionary<string, JsonNode?> InitializeDictionary()
 0241        {
 0242            GetUnderlyingRepresentation(out OrderedDictionary<string, JsonNode?>? dictionary, out JsonElement? jsonEleme
 243
 0244            if (dictionary is null)
 0245            {
 0246                OrderedDictionary<string, JsonNode?> newDictionary = CreateDictionary(Options);
 247
 0248                if (jsonElement.HasValue)
 0249                {
 0250                    foreach (JsonProperty jElementProperty in jsonElement.Value.EnumerateObject())
 0251                    {
 0252                        JsonNode? node = JsonNodeConverter.Create(jElementProperty.Value, Options);
 0253                        node?.Parent = this;
 254
 0255                        newDictionary.Add(jElementProperty.Name, node);
 0256                    }
 0257                }
 258
 259                // Ensure only one dictionary instance is published using CompareExchange
 0260                OrderedDictionary<string, JsonNode?>? exchangedDictionary = Interlocked.CompareExchange(ref _dictionary,
 0261                if (exchangedDictionary is null)
 0262                {
 263                    // We won the race and published our dictionary
 264                    // Ensure _jsonElement is written to after _dictionary
 0265                    _jsonElement = null;
 0266                    dictionary = newDictionary;
 0267                }
 268                else
 0269                {
 270                    // Another thread won the race, use their dictionary
 0271                    dictionary = exchangedDictionary;
 0272                }
 0273            }
 274
 0275            return dictionary;
 0276        }
 277
 278        private static OrderedDictionary<string, JsonNode?> CreateDictionary(JsonNodeOptions? options, int capacity = 0)
 0279        {
 0280            StringComparer comparer = options?.PropertyNameCaseInsensitive ?? false
 0281                ? StringComparer.OrdinalIgnoreCase
 0282                : StringComparer.Ordinal;
 283
 0284            return new(capacity, comparer);
 0285        }
 286
 287        /// <summary>
 288        /// Provides a coherent view of the underlying representation of the current node.
 289        /// The jsonElement value should be consumed if and only if dictionary value is null.
 290        /// </summary>
 291        private void GetUnderlyingRepresentation(out OrderedDictionary<string, JsonNode?>? dictionary, out JsonElement? 
 0292        {
 293            // Because JsonElement cannot be read atomically there might be torn reads,
 294            // however the order of read/write operations guarantees that that's only
 295            // possible if the value of _dictionary is non-null.
 0296            jsonElement = _jsonElement;
 0297            Volatile.ReadBarrier();
 0298            dictionary = _dictionary;
 0299        }
 300    }
 301}

D:\runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Nodes\JsonObject.IList.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections;
 5using System.Collections.Generic;
 6
 7namespace System.Text.Json.Nodes
 8{
 9    public partial class JsonObject : IList<KeyValuePair<string, JsonNode?>>
 10    {
 11        /// <summary>Gets the property the specified index.</summary>
 12        /// <param name="index">The zero-based index of the pair to get.</param>
 13        /// <returns>The property at the specified index as a key/value pair.</returns>
 14        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0 or greater than or equ
 015        public KeyValuePair<string, JsonNode?> GetAt(int index) => Dictionary.GetAt(index);
 16
 17        /// <summary>Sets a new property at the specified index.</summary>
 18        /// <param name="index">The zero-based index of the property to set.</param>
 19        /// <param name="propertyName">The property name to store at the specified index.</param>
 20        /// <param name="value">The JSON value to store at the specified index.</param>
 21        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0 or greater than or equ
 22        /// <exception cref="ArgumentException"><paramref name="propertyName"/> is already specified in a different inde
 23        /// <exception cref="InvalidOperationException"><paramref name="value"/> already has a parent.</exception>
 24        public void SetAt(int index, string propertyName, JsonNode? value)
 025        {
 026            ArgumentNullException.ThrowIfNull(propertyName);
 27
 028            OrderedDictionary<string, JsonNode?> dictionary = Dictionary;
 029            KeyValuePair<string, JsonNode?> existing = dictionary.GetAt(index);
 030            dictionary.SetAt(index, propertyName, value);
 031            DetachParent(existing.Value);
 032            value?.AssignParent(this);
 033        }
 34
 35        /// <summary>Sets a new property value at the specified index.</summary>
 36        /// <param name="index">The zero-based index of the property to set.</param>
 37        /// <param name="value">The JSON value to store at the specified index.</param>
 38        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0 or greater than or equ
 39        /// <exception cref="InvalidOperationException"><paramref name="value"/> already has a parent.</exception>
 40        public void SetAt(int index, JsonNode? value)
 041        {
 042            OrderedDictionary<string, JsonNode?> dictionary = Dictionary;
 043            KeyValuePair<string, JsonNode?> existing = dictionary.GetAt(index);
 044            dictionary.SetAt(index, value);
 045            DetachParent(existing.Value);
 046            value?.AssignParent(this);
 047        }
 48
 49        /// <summary>Determines the index of a specific property name in the object.</summary>
 50        /// <param name="propertyName">The property name to locate.</param>
 51        /// <returns>The index of <paramref name="propertyName"/> if found; otherwise, -1.</returns>
 52        /// <exception cref="ArgumentNullException"><paramref name="propertyName"/> is null.</exception>
 53        public int IndexOf(string propertyName)
 054        {
 055            ArgumentNullException.ThrowIfNull(propertyName);
 56
 057            return Dictionary.IndexOf(propertyName);
 058        }
 59
 60        /// <summary>Inserts a property into the object at the specified index.</summary>
 61        /// <param name="index">The zero-based index at which the property should be inserted.</param>
 62        /// <param name="propertyName">The property name to insert.</param>
 63        /// <param name="value">The JSON value to insert.</param>
 64        /// <exception cref="ArgumentNullException"><paramref name="propertyName"/> is null.</exception>
 65        /// <exception cref="ArgumentException">An element with the same key already exists in the <see cref="JsonObject
 66        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0 or greater than <see c
 67        public void Insert(int index, string propertyName, JsonNode? value)
 068        {
 069            ArgumentNullException.ThrowIfNull(propertyName);
 70
 071            Dictionary.Insert(index, propertyName, value);
 072            value?.AssignParent(this);
 073        }
 74
 75        /// <summary>Removes the property at the specified index.</summary>
 76        /// <param name="index">The zero-based index of the item to remove.</param>
 77        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0 or greater than or equ
 78        public void RemoveAt(int index)
 079        {
 080            KeyValuePair<string, JsonNode?> existing = Dictionary.GetAt(index);
 081            Dictionary.RemoveAt(index);
 082            DetachParent(existing.Value);
 083        }
 84
 85        /// <inheritdoc />
 86        KeyValuePair<string, JsonNode?> IList<KeyValuePair<string, JsonNode?>>.this[int index]
 87        {
 088            get => GetAt(index);
 089            set => SetAt(index, value.Key, value.Value);
 90        }
 91
 92        /// <inheritdoc />
 093        int IList<KeyValuePair<string, JsonNode?>>.IndexOf(KeyValuePair<string, JsonNode?> item) => ((IList<KeyValuePair
 94
 95        /// <inheritdoc />
 096        void IList<KeyValuePair<string, JsonNode?>>.Insert(int index, KeyValuePair<string, JsonNode?> item) => Insert(in
 97
 98        /// <inheritdoc />
 099        void IList<KeyValuePair<string, JsonNode?>>.RemoveAt(int index) => RemoveAt(index);
 100    }
 101}

Methods/Properties

UnderlyingElement()
.ctor(System.Nullable`1<System.Text.Json.Nodes.JsonNodeOptions>)
.ctor(System.Collections.Generic.IEnumerable`1<System.Collections.Generic.KeyValuePair`2<System.String,System.Text.Json.Nodes.JsonNode>>,System.Nullable`1<System.Text.Json.Nodes.JsonNodeOptions>)
Create(System.Text.Json.JsonElement,System.Nullable`1<System.Text.Json.Nodes.JsonNodeOptions>)
.ctor(System.Text.Json.JsonElement,System.Nullable`1<System.Text.Json.Nodes.JsonNodeOptions>)
Dictionary()
GetItem(System.Int32)
SetItem(System.Int32,System.Text.Json.Nodes.JsonNode)
DeepCloneCore()
GetPropertyName(System.Text.Json.Nodes.JsonNode)
TryGetPropertyValue(System.String,System.Text.Json.Nodes.JsonNode&)
TryGetPropertyValue(System.String,System.Text.Json.Nodes.JsonNode&,System.Int32&)
WriteTo(System.Text.Json.Utf8JsonWriter,System.Text.Json.JsonSerializerOptions)
WriteContentsTo(System.Text.Json.Utf8JsonWriter,System.Text.Json.JsonSerializerOptions)
GetValueKindCore()
DeepEqualsCore(System.Text.Json.Nodes.JsonNode)
GetItem(System.String)
GetPath(System.Text.ValueStringBuilder&,System.Text.Json.Nodes.JsonNode)
SetItem(System.String,System.Text.Json.Nodes.JsonNode)
DetachParent(System.Text.Json.Nodes.JsonNode)
FindValue(System.Text.Json.Nodes.JsonNode)
Add(System.String,System.Text.Json.Nodes.JsonNode)
TryAdd(System.String,System.Text.Json.Nodes.JsonNode)
TryAdd(System.String,System.Text.Json.Nodes.JsonNode,System.Int32&)
Add(System.Collections.Generic.KeyValuePair`2<System.String,System.Text.Json.Nodes.JsonNode>)
Clear()
ContainsKey(System.String)
Count()
Remove(System.String)
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.Contains(System.Collections.Generic.KeyValuePair`2<System.String,System.Text.Json.Nodes.JsonNode>)
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.CopyTo(System.Collections.Generic.KeyValuePair`2<System.String,System.Text.Json.Nodes.JsonNode>[],System.Int32)
GetEnumerator()
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.Remove(System.Collections.Generic.KeyValuePair`2<System.String,System.Text.Json.Nodes.JsonNode>)
em.Collections.Generic.IDictionary<System.String,System.Text.Json.Nodes.JsonNode>.get_Keys()
em.Collections.Generic.IDictionary<System.String,System.Text.Json.Nodes.JsonNode>.get_Values()
System.Collections.Generic.IDictionary<System.String,System.Text.Json.Nodes.JsonNode>.TryGetValue(System.String,System.Text.Json.Nodes.JsonNode&)
em.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.get_IsReadOnly()
System.Collections.IEnumerable.GetEnumerator()
InitializeDictionary()
CreateDictionary(System.Nullable`1<System.Text.Json.Nodes.JsonNodeOptions>,System.Int32)
GetUnderlyingRepresentation(System.Collections.Generic.OrderedDictionary`2<System.String,System.Text.Json.Nodes.JsonNode>&,System.Nullable`1<System.Text.Json.JsonElement>&)
GetAt(System.Int32)
SetAt(System.Int32,System.String,System.Text.Json.Nodes.JsonNode)
SetAt(System.Int32,System.Text.Json.Nodes.JsonNode)
IndexOf(System.String)
Insert(System.Int32,System.String,System.Text.Json.Nodes.JsonNode)
RemoveAt(System.Int32)
em.Collections.Generic.IList<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.get_Item(System.Int32)
em.Collections.Generic.IList<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.set_Item(System.Int32,System.Collections.Generic.KeyValuePair`2<System.String,System.Text.Json.Nodes.JsonNode>)
System.Collections.Generic.IList<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.IndexOf(System.Collections.Generic.KeyValuePair`2<System.String,System.Text.Json.Nodes.JsonNode>)
System.Collections.Generic.IList<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.Insert(System.Int32,System.Collections.Generic.KeyValuePair`2<System.String,System.Text.Json.Nodes.JsonNode>)
System.Collections.Generic.IList<System.Collections.Generic.KeyValuePair<System.String,System.Text.Json.Nodes.JsonNode>>.RemoveAt(System.Int32)