< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 290
Coverable lines: 290
Total lines: 792
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 104
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%660%
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)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/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}
 386

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/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            if (propertyName is null)
 058            {
 059                ThrowHelper.ThrowArgumentNullException(nameof(propertyName));
 60            }
 061            bool success = Dictionary.TryAdd(propertyName, value, out index);
 062            if (success)
 063            {
 064                value?.AssignParent(this);
 065            }
 066            return success;
 067        }
 68
 69        /// <summary>
 70        ///   Adds the specified property to the <see cref="JsonObject"/>.
 71        /// </summary>
 72        /// <param name="property">
 73        ///   The KeyValuePair structure representing the property name and value to add to the <see cref="JsonObject"/>
 74        /// </param>
 75        /// <exception cref="ArgumentException">
 76        ///   An element with the same property name already exists in the <see cref="JsonObject"/>.
 77        /// </exception>
 78        /// <exception cref="ArgumentNullException">
 79        ///   The property name of <paramref name="property"/> is <see langword="null"/>.
 80        /// </exception>
 081        public void Add(KeyValuePair<string, JsonNode?> property) => Add(property.Key, property.Value);
 82
 83        /// <summary>
 84        ///   Removes all elements from the <see cref="JsonObject"/>.
 85        /// </summary>
 86        public void Clear()
 087        {
 088            OrderedDictionary<string, JsonNode?>? dictionary = _dictionary;
 89
 090            if (dictionary is null)
 091            {
 092                _jsonElement = null;
 093                return;
 94            }
 95
 096            foreach (JsonNode? node in dictionary.Values)
 097            {
 098                DetachParent(node);
 099            }
 100
 0101            dictionary.Clear();
 0102        }
 103
 104        /// <summary>
 105        ///   Determines whether the <see cref="JsonObject"/> contains an element with the specified property name.
 106        /// </summary>
 107        /// <param name="propertyName">The property name to locate in the <see cref="JsonObject"/>.</param>
 108        /// <returns>
 109        ///   <see langword="true"/> if the <see cref="JsonObject"/> contains an element with the specified property nam
 110        /// </returns>
 111        /// <exception cref="ArgumentNullException">
 112        ///   <paramref name="propertyName"/> is <see langword="null"/>.
 113        /// </exception>
 114        public bool ContainsKey(string propertyName)
 0115        {
 0116            ArgumentNullException.ThrowIfNull(propertyName);
 117
 0118            return Dictionary.ContainsKey(propertyName);
 0119        }
 120
 121        /// <summary>
 122        ///   Gets the number of elements contained in <see cref="JsonObject"/>.
 123        /// </summary>
 0124        public int Count => Dictionary.Count;
 125
 126        /// <summary>
 127        ///   Removes the element with the specified property name from the <see cref="JsonObject"/>.
 128        /// </summary>
 129        /// <param name="propertyName">The property name of the element to remove.</param>
 130        /// <returns>
 131        ///   <see langword="true"/> if the element is successfully removed; otherwise, <see langword="false"/>.
 132        /// </returns>
 133        /// <exception cref="ArgumentNullException">
 134        ///   <paramref name="propertyName"/> is <see langword="null"/>.
 135        /// </exception>
 136        public bool Remove(string propertyName)
 0137        {
 0138            ArgumentNullException.ThrowIfNull(propertyName);
 139
 0140            bool success = Dictionary.Remove(propertyName, out JsonNode? removedNode);
 0141            if (success)
 0142            {
 0143                DetachParent(removedNode);
 0144            }
 145
 0146            return success;
 0147        }
 148
 149        /// <summary>
 150        ///   Determines whether the <see cref="JsonObject"/> contains a specific property name and <see cref="JsonNode"
 151        /// </summary>
 152        /// <param name="item">The element to locate in the <see cref="JsonObject"/>.</param>
 153        /// <returns>
 154        ///   <see langword="true"/> if the <see cref="JsonObject"/> contains an element with the property name; otherwi
 155        /// </returns>
 156        bool ICollection<KeyValuePair<string, JsonNode?>>.Contains(KeyValuePair<string, JsonNode?> item) =>
 0157            ((IDictionary<string, JsonNode?>)Dictionary).Contains(item);
 158
 159        /// <summary>
 160        ///   Copies the elements of the <see cref="JsonObject"/> to an array of type KeyValuePair starting at the speci
 161        /// </summary>
 162        /// <param name="array">
 163        ///   The one-dimensional Array that is the destination of the elements copied from <see cref="JsonObject"/>.
 164        /// </param>
 165        /// <param name="index">The zero-based index in <paramref name="array"/> at which copying begins.</param>
 166        /// <exception cref="ArgumentNullException">
 167        ///   <paramref name="array"/> is <see langword="null"/>.
 168        /// </exception>
 169        /// <exception cref="ArgumentOutOfRangeException">
 170        ///   <paramref name="index"/> is less than 0.
 171        /// </exception>
 172        /// <exception cref="ArgumentException">
 173        ///   The number of elements in the source ICollection is greater than the available space from <paramref name="
 174        ///   to the end of the destination <paramref name="array"/>.
 175        /// </exception>
 176        void ICollection<KeyValuePair<string, JsonNode?>>.CopyTo(KeyValuePair<string, JsonNode?>[] array, int index) =>
 0177            ((IDictionary<string, JsonNode?>)Dictionary).CopyTo(array, index);
 178
 179        /// <summary>
 180        ///   Returns an enumerator that iterates through the <see cref="JsonObject"/>.
 181        /// </summary>
 182        /// <returns>
 183        ///   An enumerator that iterates through the <see cref="JsonObject"/>.
 184        /// </returns>
 0185        public IEnumerator<KeyValuePair<string, JsonNode?>> GetEnumerator() => Dictionary.GetEnumerator();
 186
 187        /// <summary>
 188        ///   Removes a key and value from the <see cref="JsonObject"/>.
 189        /// </summary>
 190        /// <param name="item">
 191        ///   The KeyValuePair structure representing the property name and value to remove from the <see cref="JsonObje
 192        /// </param>
 193        /// <returns>
 194        ///   <see langword="true"/> if the element is successfully removed; otherwise, <see langword="false"/>.
 195        /// </returns>
 0196        bool ICollection<KeyValuePair<string, JsonNode?>>.Remove(KeyValuePair<string, JsonNode?> item) => Remove(item.Ke
 197
 198        /// <summary>
 199        ///   Gets a collection containing the property names in the <see cref="JsonObject"/>.
 200        /// </summary>
 0201        ICollection<string> IDictionary<string, JsonNode?>.Keys => Dictionary.Keys;
 202
 203        /// <summary>
 204        ///   Gets a collection containing the property values in the <see cref="JsonObject"/>.
 205        /// </summary>
 0206        ICollection<JsonNode?> IDictionary<string, JsonNode?>.Values => Dictionary.Values;
 207
 208        /// <summary>
 209        ///   Gets the value associated with the specified property name.
 210        /// </summary>
 211        /// <param name="propertyName">The property name of the value to get.</param>
 212        /// <param name="jsonNode">
 213        ///   When this method returns, contains the value associated with the specified property name, if the property 
 214        ///   otherwise, <see langword="null"/>.
 215        /// </param>
 216        /// <returns>
 217        ///   <see langword="true"/> if the <see cref="JsonObject"/> contains an element with the specified property nam
 218        /// </returns>
 219        /// <exception cref="ArgumentNullException">
 220        ///   <paramref name="propertyName"/> is <see langword="null"/>.
 221        /// </exception>
 222        bool IDictionary<string, JsonNode?>.TryGetValue(string propertyName, out JsonNode? jsonNode)
 0223        {
 0224            ArgumentNullException.ThrowIfNull(propertyName);
 225
 0226            return Dictionary.TryGetValue(propertyName, out jsonNode);
 0227        }
 228
 229        /// <summary>
 230        ///   Returns <see langword="false"/>.
 231        /// </summary>
 0232        bool ICollection<KeyValuePair<string, JsonNode?>>.IsReadOnly => false;
 233
 234        /// <summary>
 235        ///   Returns an enumerator that iterates through the <see cref="JsonObject"/>.
 236        /// </summary>
 237        /// <returns>
 238        ///   An enumerator that iterates through the <see cref="JsonObject"/>.
 239        /// </returns>
 0240        IEnumerator IEnumerable.GetEnumerator() => Dictionary.GetEnumerator();
 241
 242        private OrderedDictionary<string, JsonNode?> InitializeDictionary()
 0243        {
 0244            GetUnderlyingRepresentation(out OrderedDictionary<string, JsonNode?>? dictionary, out JsonElement? jsonEleme
 245
 0246            if (dictionary is null)
 0247            {
 0248                OrderedDictionary<string, JsonNode?> newDictionary = CreateDictionary(Options);
 249
 0250                if (jsonElement.HasValue)
 0251                {
 0252                    foreach (JsonProperty jElementProperty in jsonElement.Value.EnumerateObject())
 0253                    {
 0254                        JsonNode? node = JsonNodeConverter.Create(jElementProperty.Value, Options);
 0255                        node?.Parent = this;
 256
 0257                        newDictionary.Add(jElementProperty.Name, node);
 0258                    }
 0259                }
 260
 261                // Ensure only one dictionary instance is published using CompareExchange
 0262                OrderedDictionary<string, JsonNode?>? exchangedDictionary = Interlocked.CompareExchange(ref _dictionary,
 0263                if (exchangedDictionary is null)
 0264                {
 265                    // We won the race and published our dictionary
 266                    // Ensure _jsonElement is written to after _dictionary
 0267                    _jsonElement = null;
 0268                    dictionary = newDictionary;
 0269                }
 270                else
 0271                {
 272                    // Another thread won the race, use their dictionary
 0273                    dictionary = exchangedDictionary;
 0274                }
 0275            }
 276
 0277            return dictionary;
 0278        }
 279
 280        private static OrderedDictionary<string, JsonNode?> CreateDictionary(JsonNodeOptions? options, int capacity = 0)
 0281        {
 0282            StringComparer comparer = options?.PropertyNameCaseInsensitive ?? false
 0283                ? StringComparer.OrdinalIgnoreCase
 0284                : StringComparer.Ordinal;
 285
 0286            return new(capacity, comparer);
 0287        }
 288
 289        /// <summary>
 290        /// Provides a coherent view of the underlying representation of the current node.
 291        /// The jsonElement value should be consumed if and only if dictionary value is null.
 292        /// </summary>
 293        private void GetUnderlyingRepresentation(out OrderedDictionary<string, JsonNode?>? dictionary, out JsonElement? 
 0294        {
 295            // Because JsonElement cannot be read atomically there might be torn reads,
 296            // however the order of read/write operations guarantees that that's only
 297            // possible if the value of _dictionary is non-null.
 0298            jsonElement = _jsonElement;
 0299            Interlocked.MemoryBarrier();
 0300            dictionary = _dictionary;
 0301        }
 302    }
 303}
 304

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/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}
 102

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)