<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />

JContainer

Represents a token that can contain other tokens.
using Newtonsoft.Json.Utilities; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; using System.Threading; namespace Newtonsoft.Json.Linq { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public abstract class JContainer : JToken, IList<JToken>, ICollection<JToken>, IEnumerable<JToken>, IEnumerable, ITypedList, IBindingList, IList, ICollection { [System.Runtime.CompilerServices.Nullable(2)] internal ListChangedEventHandler _listChanged; [System.Runtime.CompilerServices.Nullable(2)] internal AddingNewEventHandler _addingNew; [System.Runtime.CompilerServices.Nullable(2)] private object _syncRoot; private bool _busy; protected abstract IList<JToken> ChildrenTokens { get; } public override bool HasValues => ChildrenTokens.Count > 0; [System.Runtime.CompilerServices.Nullable(2)] public override JToken First { [System.Runtime.CompilerServices.NullableContext(2)] get { IList<JToken> childrenTokens = ChildrenTokens; if (childrenTokens.Count <= 0) return null; return childrenTokens[0]; } } [System.Runtime.CompilerServices.Nullable(2)] public override JToken Last { [System.Runtime.CompilerServices.NullableContext(2)] get { IList<JToken> childrenTokens = ChildrenTokens; int count = childrenTokens.Count; if (count <= 0) return null; return childrenTokens[count - 1]; } } JToken IList<JToken>.this[int index] { get { return GetItem(index); } set { SetItem(index, value); } } bool ICollection<JToken>.IsReadOnly { get { return false; } } bool IList.IsFixedSize { get { return false; } } bool IList.IsReadOnly { get { return false; } } [System.Runtime.CompilerServices.Nullable(2)] object IList.this[int index] { [System.Runtime.CompilerServices.NullableContext(2)] get { return GetItem(index); } [System.Runtime.CompilerServices.NullableContext(2)] set { SetItem(index, EnsureValue(value)); } } public int Count => ChildrenTokens.Count; bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { if (_syncRoot == null) Interlocked.CompareExchange(ref _syncRoot, new object(), null); return _syncRoot; } } bool IBindingList.AllowEdit { get { return true; } } bool IBindingList.AllowNew { get { return true; } } bool IBindingList.AllowRemove { get { return true; } } bool IBindingList.IsSorted { get { return false; } } ListSortDirection IBindingList.SortDirection { get { return ListSortDirection.Ascending; } } [System.Runtime.CompilerServices.Nullable(2)] PropertyDescriptor IBindingList.SortProperty { [System.Runtime.CompilerServices.NullableContext(2)] get { return null; } } bool IBindingList.SupportsChangeNotification { get { return true; } } bool IBindingList.SupportsSearching { get { return false; } } bool IBindingList.SupportsSorting { get { return false; } } public event ListChangedEventHandler ListChanged { add { _listChanged = (ListChangedEventHandler)Delegate.Combine(_listChanged, value); } remove { _listChanged = (ListChangedEventHandler)Delegate.Remove(_listChanged, value); } } public event AddingNewEventHandler AddingNew { add { _addingNew = (AddingNewEventHandler)Delegate.Combine(_addingNew, value); } remove { _addingNew = (AddingNewEventHandler)Delegate.Remove(_addingNew, value); } } internal JContainer() { } internal JContainer(JContainer other, [System.Runtime.CompilerServices.Nullable(2)] JsonCloneSettings settings) : this() { ValidationUtils.ArgumentNotNull(other, "other"); bool flag = settings?.CopyAnnotations ?? true; if (flag) CopyAnnotations(this, other); int num = 0; foreach (JToken item in (IEnumerable<JToken>)other) { TryAddInternal(num, item, false, flag); num++; } } internal void CheckReentrancy() { if (_busy) throw new InvalidOperationException("Cannot change {0} during a collection change event.".FormatWith(CultureInfo.InvariantCulture, GetType())); } internal virtual IList<JToken> CreateChildrenCollection() { return new List<JToken>(); } protected virtual void OnAddingNew(AddingNewEventArgs e) { _addingNew?.Invoke(this, e); } protected virtual void OnListChanged(ListChangedEventArgs e) { ListChangedEventHandler listChanged = _listChanged; if (listChanged != null) { _busy = true; try { listChanged(this, e); } finally { _busy = false; } } } internal bool ContentsEqual(JContainer container) { if (container == this) return true; IList<JToken> childrenTokens = ChildrenTokens; IList<JToken> childrenTokens2 = container.ChildrenTokens; if (childrenTokens.Count != childrenTokens2.Count) return false; for (int i = 0; i < childrenTokens.Count; i++) { if (!childrenTokens[i].DeepEquals(childrenTokens2[i])) return false; } return true; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public override JEnumerable<JToken> Children() { return new JEnumerable<JToken>(ChildrenTokens); } [System.Runtime.CompilerServices.NullableContext(2)] [return: System.Runtime.CompilerServices.Nullable(new byte[] { 1, 2 })] public override IEnumerable<T> Values<T>() { return ChildrenTokens.Convert<JToken, T>(); } public IEnumerable<JToken> Descendants() { return GetDescendants(false); } public IEnumerable<JToken> DescendantsAndSelf() { return GetDescendants(true); } internal IEnumerable<JToken> GetDescendants(bool self) { if (self) yield return (JToken)this; foreach (JToken childrenToken in ChildrenTokens) { yield return childrenToken; JContainer jContainer = childrenToken as JContainer; if (jContainer != null) { foreach (JToken item in jContainer.Descendants()) { yield return item; } } } } [System.Runtime.CompilerServices.NullableContext(2)] internal bool IsMultiContent([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] object content) { if (content is IEnumerable && !(content is string) && !(content is JToken)) return !(content is byte[]); return false; } internal JToken EnsureParentToken([System.Runtime.CompilerServices.Nullable(2)] JToken item, bool skipParentCheck, bool copyAnnotations) { if (item == null) return JValue.CreateNull(); if (skipParentCheck) return item; if (item.Parent != null || item == this || (item.HasValues && base.Root == item)) { JsonCloneSettings settings = copyAnnotations ? null : JsonCloneSettings.SkipCopyAnnotations; item = item.CloneToken(settings); } return item; } [System.Runtime.CompilerServices.NullableContext(2)] internal abstract int IndexOfItem(JToken item); [System.Runtime.CompilerServices.NullableContext(2)] internal virtual bool InsertItem(int index, JToken item, bool skipParentCheck, bool copyAnnotations) { IList<JToken> childrenTokens = ChildrenTokens; if (index > childrenTokens.Count) throw new ArgumentOutOfRangeException("index", "Index must be within the bounds of the List."); CheckReentrancy(); item = EnsureParentToken(item, skipParentCheck, copyAnnotations); JToken jToken = (index == 0) ? null : childrenTokens[index - 1]; JToken jToken2 = (index == childrenTokens.Count) ? null : childrenTokens[index]; ValidateToken(item, null); item.Parent = this; item.Previous = jToken; if (jToken != null) jToken.Next = item; item.Next = jToken2; if (jToken2 != null) jToken2.Previous = item; childrenTokens.Insert(index, item); if (_listChanged != null) OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index)); return true; } internal virtual void RemoveItemAt(int index) { IList<JToken> childrenTokens = ChildrenTokens; if (index < 0) throw new ArgumentOutOfRangeException("index", "Index is less than 0."); if (index >= childrenTokens.Count) throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count."); CheckReentrancy(); JToken jToken = childrenTokens[index]; JToken jToken2 = (index == 0) ? null : childrenTokens[index - 1]; JToken jToken3 = (index == childrenTokens.Count - 1) ? null : childrenTokens[index + 1]; if (jToken2 != null) jToken2.Next = jToken3; if (jToken3 != null) jToken3.Previous = jToken2; jToken.Parent = null; jToken.Previous = null; jToken.Next = null; childrenTokens.RemoveAt(index); if (_listChanged != null) OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index)); } [System.Runtime.CompilerServices.NullableContext(2)] internal virtual bool RemoveItem(JToken item) { if (item != null) { int num = IndexOfItem(item); if (num >= 0) { RemoveItemAt(num); return true; } } return false; } internal virtual JToken GetItem(int index) { return ChildrenTokens[index]; } [System.Runtime.CompilerServices.NullableContext(2)] internal virtual void SetItem(int index, JToken item) { IList<JToken> childrenTokens = ChildrenTokens; if (index < 0) throw new ArgumentOutOfRangeException("index", "Index is less than 0."); if (index >= childrenTokens.Count) throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count."); JToken jToken = childrenTokens[index]; if (!IsTokenUnchanged(jToken, item)) { CheckReentrancy(); item = EnsureParentToken(item, false, true); ValidateToken(item, jToken); JToken jToken2 = (index == 0) ? null : childrenTokens[index - 1]; JToken jToken3 = (index == childrenTokens.Count - 1) ? null : childrenTokens[index + 1]; item.Parent = this; item.Previous = jToken2; if (jToken2 != null) jToken2.Next = item; item.Next = jToken3; if (jToken3 != null) jToken3.Previous = item; childrenTokens[index] = item; jToken.Parent = null; jToken.Previous = null; jToken.Next = null; if (_listChanged != null) OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index)); } } internal virtual void ClearItems() { CheckReentrancy(); IList<JToken> childrenTokens = ChildrenTokens; foreach (JToken item in childrenTokens) { item.Parent = null; item.Previous = null; item.Next = null; } childrenTokens.Clear(); if (_listChanged != null) OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); } internal virtual void ReplaceItem(JToken existing, JToken replacement) { if (existing != null && existing.Parent == this) { int index = IndexOfItem(existing); SetItem(index, replacement); } } [System.Runtime.CompilerServices.NullableContext(2)] internal virtual bool ContainsItem(JToken item) { return IndexOfItem(item) != -1; } internal virtual void CopyItemsTo(Array array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array"); if (arrayIndex < 0) throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0."); if (arrayIndex >= array.Length && arrayIndex != 0) throw new ArgumentException("arrayIndex is equal to or greater than the length of array."); if (Count > array.Length - arrayIndex) throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array."); int num = 0; foreach (JToken childrenToken in ChildrenTokens) { array.SetValue(childrenToken, arrayIndex + num); num++; } } internal static bool IsTokenUnchanged(JToken currentValue, [System.Runtime.CompilerServices.Nullable(2)] JToken newValue) { JValue jValue = currentValue as JValue; if (jValue != null) { if (newValue == null) return jValue.Type == JTokenType.Null; return jValue.Equals(newValue); } return false; } internal virtual void ValidateToken(JToken o, [System.Runtime.CompilerServices.Nullable(2)] JToken existing) { ValidationUtils.ArgumentNotNull(o, "o"); if (o.Type == JTokenType.Property) throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType())); } [System.Runtime.CompilerServices.NullableContext(2)] public virtual void Add(object content) { TryAddInternal(ChildrenTokens.Count, content, false, true); } [System.Runtime.CompilerServices.NullableContext(2)] internal bool TryAdd(object content) { return TryAddInternal(ChildrenTokens.Count, content, false, true); } internal void AddAndSkipParentCheck(JToken token) { TryAddInternal(ChildrenTokens.Count, token, true, true); } [System.Runtime.CompilerServices.NullableContext(2)] public void AddFirst(object content) { TryAddInternal(0, content, false, true); } [System.Runtime.CompilerServices.NullableContext(2)] internal bool TryAddInternal(int index, object content, bool skipParentCheck, bool copyAnnotations) { if (IsMultiContent(content)) { IEnumerable obj = (IEnumerable)content; int num = index; foreach (object item2 in obj) { TryAddInternal(num, item2, skipParentCheck, copyAnnotations); num++; } return true; } JToken item = CreateFromContent(content); return InsertItem(index, item, skipParentCheck, copyAnnotations); } internal static JToken CreateFromContent([System.Runtime.CompilerServices.Nullable(2)] object content) { JToken jToken = content as JToken; if (jToken != null) return jToken; return new JValue(content); } public JsonWriter CreateWriter() { return new JTokenWriter(this); } public void ReplaceAll(object content) { ClearItems(); Add(content); } public void RemoveAll() { ClearItems(); } internal abstract void MergeItem(object content, [System.Runtime.CompilerServices.Nullable(2)] JsonMergeSettings settings); [System.Runtime.CompilerServices.NullableContext(2)] public void Merge(object content) { if (content != null) { ValidateContent(content); MergeItem(content, null); } } [System.Runtime.CompilerServices.NullableContext(2)] public void Merge(object content, JsonMergeSettings settings) { if (content != null) { ValidateContent(content); MergeItem(content, settings); } } private void ValidateContent(object content) { if (content.GetType().IsSubclassOf(typeof(JToken)) || IsMultiContent(content)) return; throw new ArgumentException("Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, content.GetType()), "content"); } internal void ReadTokenFrom(JsonReader reader, [System.Runtime.CompilerServices.Nullable(2)] JsonLoadSettings options) { int depth = reader.Depth; if (!reader.Read()) throw JsonReaderException.Create(reader, "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); ReadContentFrom(reader, options); if (reader.Depth > depth) throw JsonReaderException.Create(reader, "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); } internal void ReadContentFrom(JsonReader r, [System.Runtime.CompilerServices.Nullable(2)] JsonLoadSettings settings) { ValidationUtils.ArgumentNotNull(r, "r"); IJsonLineInfo lineInfo = r as IJsonLineInfo; JContainer jContainer = this; do { JProperty jProperty = jContainer as JProperty; if (jProperty != null && jProperty.Value != null) { if (jContainer == this) break; jContainer = jContainer.Parent; } switch (r.TokenType) { case JsonToken.StartArray: { JArray jArray = new JArray(); jArray.SetLineInfo(lineInfo, settings); jContainer.Add(jArray); jContainer = jArray; break; } case JsonToken.EndArray: if (jContainer == this) return; jContainer = jContainer.Parent; break; case JsonToken.StartObject: { JObject jObject = new JObject(); jObject.SetLineInfo(lineInfo, settings); jContainer.Add(jObject); jContainer = jObject; break; } case JsonToken.EndObject: if (jContainer == this) return; jContainer = jContainer.Parent; break; case JsonToken.StartConstructor: { JConstructor jConstructor = new JConstructor(r.Value.ToString()); jConstructor.SetLineInfo(lineInfo, settings); jContainer.Add(jConstructor); jContainer = jConstructor; break; } case JsonToken.EndConstructor: if (jContainer == this) return; jContainer = jContainer.Parent; break; case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { JValue jValue = new JValue(r.Value); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); break; } case JsonToken.Comment: if (settings != null && settings.CommentHandling == CommentHandling.Load) { JValue jValue = JValue.CreateComment(r.Value.ToString()); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); } break; case JsonToken.Null: { JValue jValue = JValue.CreateNull(); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); break; } case JsonToken.Undefined: { JValue jValue = JValue.CreateUndefined(); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); break; } case JsonToken.PropertyName: { JProperty jProperty2 = ReadProperty(r, settings, lineInfo, jContainer); if (jProperty2 != null) jContainer = jProperty2; else r.Skip(); break; } default: throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, r.TokenType)); case JsonToken.None: break; } } while (r.Read()); } [System.Runtime.CompilerServices.NullableContext(2)] private static JProperty ReadProperty([System.Runtime.CompilerServices.Nullable(1)] JsonReader r, JsonLoadSettings settings, IJsonLineInfo lineInfo, [System.Runtime.CompilerServices.Nullable(1)] JContainer parent) { DuplicatePropertyNameHandling duplicatePropertyNameHandling = settings?.DuplicatePropertyNameHandling ?? DuplicatePropertyNameHandling.Replace; JObject obj = (JObject)parent; string text = r.Value.ToString(); JProperty jProperty = obj.Property(text, StringComparison.Ordinal); if (jProperty != null) { switch (duplicatePropertyNameHandling) { case DuplicatePropertyNameHandling.Ignore: return null; case DuplicatePropertyNameHandling.Error: throw JsonReaderException.Create(r, "Property with the name '{0}' already exists in the current JSON object.".FormatWith(CultureInfo.InvariantCulture, text)); } } JProperty jProperty2 = new JProperty(text); jProperty2.SetLineInfo(lineInfo, settings); if (jProperty == null) parent.Add(jProperty2); else jProperty.Replace(jProperty2); return jProperty2; } internal int ContentsHashCode() { int num = 0; foreach (JToken childrenToken in ChildrenTokens) { num ^= childrenToken.GetDeepHashCode(); } return num; } string ITypedList.GetListName(PropertyDescriptor[] listAccessors) { return string.Empty; } PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) { return (First as ICustomTypeDescriptor)?.GetProperties() ?? new PropertyDescriptorCollection(CollectionUtils.ArrayEmpty<PropertyDescriptor>()); } int IList<JToken>.IndexOf(JToken item) { return IndexOfItem(item); } void IList<JToken>.Insert(int index, JToken item) { InsertItem(index, item, false, true); } void IList<JToken>.RemoveAt(int index) { RemoveItemAt(index); } void ICollection<JToken>.Add(JToken item) { Add(item); } void ICollection<JToken>.Clear() { ClearItems(); } bool ICollection<JToken>.Contains(JToken item) { return ContainsItem(item); } void ICollection<JToken>.CopyTo(JToken[] array, int arrayIndex) { CopyItemsTo(array, arrayIndex); } bool ICollection<JToken>.Remove(JToken item) { return RemoveItem(item); } [System.Runtime.CompilerServices.NullableContext(2)] private JToken EnsureValue(object value) { if (value == null) return null; JToken jToken = value as JToken; if (jToken != null) return jToken; throw new ArgumentException("Argument is not a JToken."); } [System.Runtime.CompilerServices.NullableContext(2)] int IList.Add(object value) { Add(EnsureValue(value)); return Count - 1; } void IList.Clear() { ClearItems(); } [System.Runtime.CompilerServices.NullableContext(2)] bool IList.Contains(object value) { return ContainsItem(EnsureValue(value)); } [System.Runtime.CompilerServices.NullableContext(2)] int IList.IndexOf(object value) { return IndexOfItem(EnsureValue(value)); } [System.Runtime.CompilerServices.NullableContext(2)] void IList.Insert(int index, object value) { InsertItem(index, EnsureValue(value), false, false); } [System.Runtime.CompilerServices.NullableContext(2)] void IList.Remove(object value) { RemoveItem(EnsureValue(value)); } void IList.RemoveAt(int index) { RemoveItemAt(index); } void ICollection.CopyTo(Array array, int index) { CopyItemsTo(array, index); } void IBindingList.AddIndex(PropertyDescriptor property) { } object IBindingList.AddNew() { AddingNewEventArgs addingNewEventArgs = new AddingNewEventArgs(); OnAddingNew(addingNewEventArgs); if (addingNewEventArgs.NewObject == null) throw new JsonException("Could not determine new value to add to '{0}'.".FormatWith(CultureInfo.InvariantCulture, GetType())); JToken jToken = addingNewEventArgs.NewObject as JToken; if (jToken == null) throw new JsonException("New item to be added to collection must be compatible with {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JToken))); Add(jToken); return jToken; } void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) { throw new NotSupportedException(); } int IBindingList.Find(PropertyDescriptor property, object key) { throw new NotSupportedException(); } void IBindingList.RemoveIndex(PropertyDescriptor property) { } void IBindingList.RemoveSort() { throw new NotSupportedException(); } internal static void MergeEnumerableContent(JContainer target, IEnumerable content, [System.Runtime.CompilerServices.Nullable(2)] JsonMergeSettings settings) { switch (settings?.MergeArrayHandling ?? MergeArrayHandling.Concat) { case MergeArrayHandling.Concat: foreach (object item in content) { target.Add(CreateFromContent(item)); } break; case MergeArrayHandling.Union: { Dictionary<JToken, bool> dictionary = new Dictionary<JToken, bool>(JToken.EqualityComparer); foreach (JToken item2 in (IEnumerable<JToken>)target) { dictionary[item2] = true; } foreach (object item3 in content) { JToken jToken2 = CreateFromContent(item3); if (!dictionary.ContainsKey(jToken2)) { dictionary[jToken2] = true; target.Add(jToken2); } } break; } case MergeArrayHandling.Replace: if (target != content) { target.ClearItems(); foreach (object item4 in content) { target.Add(CreateFromContent(item4)); } } break; case MergeArrayHandling.Merge: { int num = 0; foreach (object item5 in content) { if (num < target.Count) { JContainer jContainer = target[num] as JContainer; if (jContainer != null) jContainer.Merge(item5, settings); else if (item5 != null) { JToken jToken = CreateFromContent(item5); if (jToken.Type != JTokenType.Null) target[num] = jToken; } } else target.Add(CreateFromContent(item5)); num++; } break; } default: throw new ArgumentOutOfRangeException("settings", "Unexpected merge array handling when merging JSON."); } } } }