JProperty
Represents a JSON property.
using Newtonsoft.Json.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
namespace Newtonsoft.Json.Linq
{
public class JProperty : JContainer
{
private class JPropertyList : IList<JToken>, ICollection<JToken>, IEnumerable<JToken>, IEnumerable
{
internal JToken _token;
public int Count {
get {
if (_token == null)
return 0;
return 1;
}
}
public bool IsReadOnly => false;
public JToken this[int index] {
get {
if (index != 0)
return null;
return _token;
}
set {
if (index == 0)
_token = value;
}
}
public IEnumerator<JToken> GetEnumerator()
{
if (_token != null)
yield return _token;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(JToken item)
{
_token = item;
}
public void Clear()
{
_token = null;
}
public bool Contains(JToken item)
{
return _token == item;
}
public void CopyTo(JToken[] array, int arrayIndex)
{
if (_token != null)
array[arrayIndex] = _token;
}
public bool Remove(JToken item)
{
if (_token == item) {
_token = null;
return true;
}
return false;
}
public int IndexOf(JToken item)
{
if (_token != item)
return -1;
return 0;
}
public void Insert(int index, JToken item)
{
if (index == 0)
_token = item;
}
public void RemoveAt(int index)
{
if (index == 0)
_token = null;
}
}
private readonly JPropertyList _content = new JPropertyList();
private readonly string _name;
protected override IList<JToken> ChildrenTokens => _content;
public string Name {
[DebuggerStepThrough]
get {
return _name;
}
}
public new JToken Value {
[DebuggerStepThrough]
get {
return _content._token;
}
set {
CheckReentrancy();
JToken item = value ?? JValue.CreateNull();
if (_content._token == null)
InsertItem(0, item, false);
else
SetItem(0, item);
}
}
public override JTokenType Type {
[DebuggerStepThrough]
get {
return JTokenType.Property;
}
}
public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters)
{
Task task = writer.WritePropertyNameAsync(_name, cancellationToken);
if (task.IsCompletedSucessfully())
return WriteValueAsync(writer, cancellationToken, converters);
return WriteToAsync(task, writer, cancellationToken, converters);
}
private async Task WriteToAsync(Task task, JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters)
{
await task.ConfigureAwait(false);
await WriteValueAsync(writer, cancellationToken, converters).ConfigureAwait(false);
}
private Task WriteValueAsync(JsonWriter writer, CancellationToken cancellationToken, JsonConverter[] converters)
{
JToken value = Value;
if (value == null)
return writer.WriteNullAsync(cancellationToken);
return value.WriteToAsync(writer, cancellationToken, converters);
}
public new static Task<JProperty> LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken))
{
return LoadAsync(reader, null, cancellationToken);
}
public new static async Task<JProperty> LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default(CancellationToken))
{
if (reader.TokenType == JsonToken.None && !(await reader.ReadAsync(cancellationToken).ConfigureAwait(false)))
throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader.");
await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(false);
if (reader.TokenType != JsonToken.PropertyName)
throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
JProperty p = new JProperty((string)reader.Value);
p.SetLineInfo(reader as IJsonLineInfo, settings);
await p.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false);
return p;
}
public JProperty(JProperty other)
: base(other)
{
_name = other.Name;
}
internal override JToken GetItem(int index)
{
if (index != 0)
throw new ArgumentOutOfRangeException();
return Value;
}
internal override void SetItem(int index, JToken item)
{
if (index != 0)
throw new ArgumentOutOfRangeException();
if (!JContainer.IsTokenUnchanged(Value, item)) {
((JObject)base.Parent)?.InternalPropertyChanging(this);
base.SetItem(0, item);
((JObject)base.Parent)?.InternalPropertyChanged(this);
}
}
internal override bool RemoveItem(JToken item)
{
throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
}
internal override void RemoveItemAt(int index)
{
throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
}
internal override int IndexOfItem(JToken item)
{
return _content.IndexOf(item);
}
internal override void InsertItem(int index, JToken item, bool skipParentCheck)
{
if (item == null || item.Type != JTokenType.Comment) {
if (Value != null)
throw new JsonException("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
base.InsertItem(0, item, false);
}
}
internal override bool ContainsItem(JToken item)
{
return Value == item;
}
internal override void MergeItem(object content, JsonMergeSettings settings)
{
JToken jToken = (content as JProperty)?.Value;
if (jToken != null && jToken.Type != JTokenType.Null)
Value = jToken;
}
internal override void ClearItems()
{
throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
}
internal override bool DeepEquals(JToken node)
{
JProperty jProperty;
if ((jProperty = (node as JProperty)) != null && _name == jProperty.Name)
return ContentsEqual(jProperty);
return false;
}
internal override JToken CloneToken()
{
return new JProperty(this);
}
internal JProperty(string name)
{
ValidationUtils.ArgumentNotNull(name, "name");
_name = name;
}
public JProperty(string name, params object[] content)
: this(name, (object)content)
{
}
public JProperty(string name, object content)
{
ValidationUtils.ArgumentNotNull(name, "name");
_name = name;
Value = (IsMultiContent(content) ? new JArray(content) : JContainer.CreateFromContent(content));
}
public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
{
writer.WritePropertyName(_name);
JToken value = Value;
if (value != null)
value.WriteTo(writer, converters);
else
writer.WriteNull();
}
internal override int GetDeepHashCode()
{
return _name.GetHashCode() ^ (Value?.GetDeepHashCode() ?? 0);
}
public new static JProperty Load(JsonReader reader)
{
return Load(reader, null);
}
public new static JProperty Load(JsonReader reader, JsonLoadSettings settings)
{
if (reader.TokenType == JsonToken.None && !reader.Read())
throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader.");
reader.MoveToContent();
if (reader.TokenType != JsonToken.PropertyName)
throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
JProperty jProperty = new JProperty((string)reader.Value);
jProperty.SetLineInfo(reader as IJsonLineInfo, settings);
jProperty.ReadTokenFrom(reader, settings);
return jProperty;
}
}
}