JsonElement
Represents a specific JSON value within a JsonDocument.
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System.Text.Json
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public readonly struct JsonElement
{
[DebuggerDisplay("{Current,nq}")]
public struct ArrayEnumerator : IEnumerable<JsonElement>, IEnumerable, IEnumerator<JsonElement>, IEnumerator, IDisposable
{
private readonly JsonElement _target;
private int _curIdx;
private readonly int _endIdxOrVersion;
public JsonElement Current {
get {
if (_curIdx < 0)
return default(JsonElement);
return new JsonElement(_target._parent, _curIdx);
}
}
[System.Runtime.CompilerServices.Nullable(1)]
object IEnumerator.Current {
get {
return Current;
}
}
internal ArrayEnumerator(JsonElement target)
{
_target = target;
_curIdx = -1;
_endIdxOrVersion = target._parent.GetEndIndex(_target._idx, false);
}
public ArrayEnumerator GetEnumerator()
{
ArrayEnumerator result = this;
result._curIdx = -1;
return result;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator<JsonElement> IEnumerable<JsonElement>.GetEnumerator()
{
return GetEnumerator();
}
public void Dispose()
{
_curIdx = _endIdxOrVersion;
}
public void Reset()
{
_curIdx = -1;
}
public bool MoveNext()
{
if (_curIdx >= _endIdxOrVersion)
return false;
if (_curIdx < 0)
_curIdx = _target._idx + 12;
else
_curIdx = _target._parent.GetEndIndex(_curIdx, true);
return _curIdx < _endIdxOrVersion;
}
}
[DebuggerDisplay("{Current,nq}")]
public struct ObjectEnumerator : IEnumerable<JsonProperty>, IEnumerable, IEnumerator<JsonProperty>, IEnumerator, IDisposable
{
private readonly JsonElement _target;
private int _curIdx;
private readonly int _endIdxOrVersion;
public JsonProperty Current {
get {
if (_curIdx < 0)
return default(JsonProperty);
return new JsonProperty(new JsonElement(_target._parent, _curIdx));
}
}
[System.Runtime.CompilerServices.Nullable(1)]
object IEnumerator.Current {
get {
return Current;
}
}
internal ObjectEnumerator(JsonElement target)
{
_target = target;
_curIdx = -1;
_endIdxOrVersion = target._parent.GetEndIndex(_target._idx, false);
}
public ObjectEnumerator GetEnumerator()
{
ObjectEnumerator result = this;
result._curIdx = -1;
return result;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator<JsonProperty> IEnumerable<JsonProperty>.GetEnumerator()
{
return GetEnumerator();
}
public void Dispose()
{
_curIdx = _endIdxOrVersion;
}
public void Reset()
{
_curIdx = -1;
}
public bool MoveNext()
{
if (_curIdx >= _endIdxOrVersion)
return false;
if (_curIdx < 0)
_curIdx = _target._idx + 12;
else
_curIdx = _target._parent.GetEndIndex(_curIdx, true);
_curIdx += 12;
return _curIdx < _endIdxOrVersion;
}
}
private readonly JsonDocument _parent;
private readonly int _idx;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private JsonTokenType TokenType {
get {
return _parent?.GetJsonTokenType(_idx) ?? JsonTokenType.None;
}
}
public JsonValueKind ValueKind => TokenType.ToValueKind();
public JsonElement this[int index] {
get {
CheckValidInstance();
return _parent.GetArrayIndexElement(_idx, index);
}
}
internal bool ValueIsEscaped {
get {
CheckValidInstance();
return _parent.ValueIsEscaped(_idx, false);
}
}
internal ReadOnlySpan<byte> ValueSpan {
get {
CheckValidInstance();
return _parent.GetRawValue(_idx, false).Span;
}
}
[System.Runtime.CompilerServices.Nullable(1)]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string DebuggerDisplay {
get {
return $"""{ValueKind}""{ToString()}""";
}
}
internal JsonElement(JsonDocument parent, int idx)
{
_parent = parent;
_idx = idx;
}
public int GetArrayLength()
{
CheckValidInstance();
return _parent.GetArrayLength(_idx);
}
public int GetPropertyCount()
{
CheckValidInstance();
return _parent.GetPropertyCount(_idx);
}
[System.Runtime.CompilerServices.NullableContext(1)]
public JsonElement GetProperty(string propertyName)
{
if (propertyName == null)
ThrowHelper.ThrowArgumentNullException("propertyName");
if (TryGetProperty(propertyName, out JsonElement value))
return value;
throw new KeyNotFoundException();
}
public JsonElement GetProperty(ReadOnlySpan<char> propertyName)
{
if (TryGetProperty(propertyName, out JsonElement value))
return value;
throw new KeyNotFoundException();
}
public JsonElement GetProperty(ReadOnlySpan<byte> utf8PropertyName)
{
if (TryGetProperty(utf8PropertyName, out JsonElement value))
return value;
throw new KeyNotFoundException();
}
[System.Runtime.CompilerServices.NullableContext(1)]
public bool TryGetProperty(string propertyName, out JsonElement value)
{
if (propertyName == null)
ThrowHelper.ThrowArgumentNullException("propertyName");
return TryGetProperty(propertyName.AsSpan(), out value);
}
public bool TryGetProperty(ReadOnlySpan<char> propertyName, out JsonElement value)
{
CheckValidInstance();
return _parent.TryGetNamedPropertyValue(_idx, propertyName, out value);
}
public bool TryGetProperty(ReadOnlySpan<byte> utf8PropertyName, out JsonElement value)
{
CheckValidInstance();
return _parent.TryGetNamedPropertyValue(_idx, utf8PropertyName, out value);
}
public bool GetBoolean()
{
JsonTokenType tokenType = TokenType;
switch (tokenType) {
default:
return <GetBoolean>g__ThrowJsonElementWrongTypeException|18_0(tokenType);
case JsonTokenType.False:
return false;
case JsonTokenType.True:
return true;
}
}
[System.Runtime.CompilerServices.NullableContext(2)]
public string GetString()
{
CheckValidInstance();
return _parent.GetString(_idx, JsonTokenType.String);
}
[System.Runtime.CompilerServices.NullableContext(2)]
public bool TryGetBytesFromBase64([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out byte[] value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
[System.Runtime.CompilerServices.NullableContext(1)]
public byte[] GetBytesFromBase64()
{
if (!TryGetBytesFromBase64(out byte[] value))
ThrowHelper.ThrowFormatException();
return value;
}
[CLSCompliant(false)]
public bool TryGetSByte(out sbyte value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
[CLSCompliant(false)]
public sbyte GetSByte()
{
if (TryGetSByte(out sbyte value))
return value;
throw new FormatException();
}
public bool TryGetByte(out byte value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
public byte GetByte()
{
if (TryGetByte(out byte value))
return value;
throw new FormatException();
}
public bool TryGetInt16(out short value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
public short GetInt16()
{
if (TryGetInt16(out short value))
return value;
throw new FormatException();
}
[CLSCompliant(false)]
public bool TryGetUInt16(out ushort value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
[CLSCompliant(false)]
public ushort GetUInt16()
{
if (TryGetUInt16(out ushort value))
return value;
throw new FormatException();
}
public bool TryGetInt32(out int value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
public int GetInt32()
{
if (!TryGetInt32(out int value))
ThrowHelper.ThrowFormatException();
return value;
}
[CLSCompliant(false)]
public bool TryGetUInt32(out uint value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
[CLSCompliant(false)]
public uint GetUInt32()
{
if (!TryGetUInt32(out uint value))
ThrowHelper.ThrowFormatException();
return value;
}
public bool TryGetInt64(out long value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
public long GetInt64()
{
if (!TryGetInt64(out long value))
ThrowHelper.ThrowFormatException();
return value;
}
[CLSCompliant(false)]
public bool TryGetUInt64(out ulong value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
[CLSCompliant(false)]
public ulong GetUInt64()
{
if (!TryGetUInt64(out ulong value))
ThrowHelper.ThrowFormatException();
return value;
}
public bool TryGetDouble(out double value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
public double GetDouble()
{
if (!TryGetDouble(out double value))
ThrowHelper.ThrowFormatException();
return value;
}
public bool TryGetSingle(out float value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
public float GetSingle()
{
if (!TryGetSingle(out float value))
ThrowHelper.ThrowFormatException();
return value;
}
public bool TryGetDecimal(out decimal value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
public decimal GetDecimal()
{
if (!TryGetDecimal(out decimal value))
ThrowHelper.ThrowFormatException();
return value;
}
public bool TryGetDateTime(out DateTime value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
public DateTime GetDateTime()
{
if (!TryGetDateTime(out DateTime value))
ThrowHelper.ThrowFormatException();
return value;
}
public bool TryGetDateTimeOffset(out DateTimeOffset value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
public DateTimeOffset GetDateTimeOffset()
{
if (!TryGetDateTimeOffset(out DateTimeOffset value))
ThrowHelper.ThrowFormatException();
return value;
}
public bool TryGetGuid(out Guid value)
{
CheckValidInstance();
return _parent.TryGetValue(_idx, out value);
}
public Guid GetGuid()
{
if (!TryGetGuid(out Guid value))
ThrowHelper.ThrowFormatException();
return value;
}
internal string GetPropertyName()
{
CheckValidInstance();
return _parent.GetNameOfPropertyValue(_idx);
}
internal ReadOnlySpan<byte> GetPropertyNameRaw()
{
CheckValidInstance();
return _parent.GetPropertyNameRaw(_idx);
}
[System.Runtime.CompilerServices.NullableContext(1)]
public string GetRawText()
{
CheckValidInstance();
return _parent.GetRawValueAsString(_idx);
}
internal ReadOnlyMemory<byte> GetRawValue()
{
CheckValidInstance();
return _parent.GetRawValue(_idx, true);
}
internal string GetPropertyRawText()
{
CheckValidInstance();
return _parent.GetPropertyRawValueAsString(_idx);
}
public static bool DeepEquals(JsonElement element1, JsonElement element2)
{
if (!StackHelper.TryEnsureSufficientExecutionStack())
ThrowHelper.ThrowInsufficientExecutionStackException_JsonElementDeepEqualsInsufficientExecutionStack();
element1.CheckValidInstance();
element2.CheckValidInstance();
JsonValueKind valueKind = element1.ValueKind;
if (valueKind == element2.ValueKind) {
switch (valueKind) {
case JsonValueKind.True:
case JsonValueKind.False:
case JsonValueKind.Null:
return true;
case JsonValueKind.Number: {
ReadOnlyMemory<byte> rawValue = element1.GetRawValue();
ReadOnlySpan<byte> span = rawValue.Span;
rawValue = element2.GetRawValue();
return JsonHelpers.AreEqualJsonNumbers(span, rawValue.Span);
}
case JsonValueKind.String:
if (element2.ValueIsEscaped) {
if (element1.ValueIsEscaped)
return JsonReaderHelper.UnescapeAndCompareBothInputs(element1.ValueSpan, element2.ValueSpan);
JsonElement jsonElement = element2;
element2 = element1;
element1 = jsonElement;
}
return element1.ValueEquals(element2.ValueSpan);
case JsonValueKind.Array: {
if (element1.GetArrayLength() != element2.GetArrayLength())
return false;
ArrayEnumerator arrayEnumerator = element2.EnumerateArray();
foreach (JsonElement item in element1.EnumerateArray()) {
arrayEnumerator.MoveNext();
if (!DeepEquals(item, arrayEnumerator.Current))
return false;
}
return true;
}
default: {
int num = element1.GetPropertyCount();
if (num != element2.GetPropertyCount())
return false;
ObjectEnumerator objectEnumerator = element1.EnumerateObject();
ObjectEnumerator objectEnumerator2 = element2.EnumerateObject();
while (objectEnumerator.MoveNext()) {
objectEnumerator2.MoveNext();
JsonProperty current = objectEnumerator.Current;
JsonProperty current2 = objectEnumerator2.Current;
if (!<DeepEquals>g__NameEquals|59_1(current, current2))
return <DeepEquals>g__UnorderedObjectDeepEquals|59_0(objectEnumerator, objectEnumerator2, num);
if (!DeepEquals(current.Value, current2.Value))
return false;
num--;
}
return true;
}
}
}
return false;
}
[System.Runtime.CompilerServices.NullableContext(2)]
public bool ValueEquals(string text)
{
if (TokenType == JsonTokenType.Null)
return text == null;
return TextEqualsHelper(text.AsSpan(), false);
}
public bool ValueEquals(ReadOnlySpan<byte> utf8Text)
{
if (TokenType == JsonTokenType.Null)
return Unsafe.IsNullRef(ref MemoryMarshal.GetReference(utf8Text));
return TextEqualsHelper(utf8Text, false, true);
}
public bool ValueEquals(ReadOnlySpan<char> text)
{
if (TokenType == JsonTokenType.Null)
return Unsafe.IsNullRef(ref MemoryMarshal.GetReference(text));
return TextEqualsHelper(text, false);
}
internal bool TextEqualsHelper(ReadOnlySpan<byte> utf8Text, bool isPropertyName, bool shouldUnescape)
{
CheckValidInstance();
return _parent.TextEquals(_idx, utf8Text, isPropertyName, shouldUnescape);
}
internal bool TextEqualsHelper(ReadOnlySpan<char> text, bool isPropertyName)
{
CheckValidInstance();
return _parent.TextEquals(_idx, text, isPropertyName);
}
internal bool ValueIsEscapedHelper(bool isPropertyName)
{
CheckValidInstance();
return _parent.ValueIsEscaped(_idx, isPropertyName);
}
[System.Runtime.CompilerServices.NullableContext(1)]
public void WriteTo(Utf8JsonWriter writer)
{
if (writer == null)
ThrowHelper.ThrowArgumentNullException("writer");
CheckValidInstance();
_parent.WriteElementTo(_idx, writer);
}
internal void WritePropertyNameTo(Utf8JsonWriter writer)
{
CheckValidInstance();
_parent.WritePropertyName(_idx, writer);
}
public ArrayEnumerator EnumerateArray()
{
CheckValidInstance();
JsonTokenType tokenType = TokenType;
if (tokenType != JsonTokenType.StartArray)
ThrowHelper.ThrowJsonElementWrongTypeException(JsonTokenType.StartArray, tokenType);
return new ArrayEnumerator(this);
}
public ObjectEnumerator EnumerateObject()
{
CheckValidInstance();
JsonTokenType tokenType = TokenType;
if (tokenType != JsonTokenType.StartObject)
ThrowHelper.ThrowJsonElementWrongTypeException(JsonTokenType.StartObject, tokenType);
return new ObjectEnumerator(this);
}
[System.Runtime.CompilerServices.NullableContext(1)]
public override string ToString()
{
switch (TokenType) {
case JsonTokenType.None:
case JsonTokenType.Null:
return string.Empty;
case JsonTokenType.True:
return bool.TrueString;
case JsonTokenType.False:
return bool.FalseString;
case JsonTokenType.StartObject:
case JsonTokenType.StartArray:
case JsonTokenType.Number:
return _parent.GetRawValueAsString(_idx);
case JsonTokenType.String:
return GetString();
default:
return string.Empty;
}
}
public JsonElement Clone()
{
CheckValidInstance();
if (!_parent.IsDisposable)
return this;
return _parent.CloneElement(_idx);
}
private void CheckValidInstance()
{
if (_parent == null)
throw new InvalidOperationException();
}
public static JsonElement ParseValue(ref Utf8JsonReader reader)
{
JsonDocument.TryParseValue(ref reader, out JsonDocument document, true, false);
return document.RootElement;
}
internal static JsonElement ParseValue(Stream utf8Json, JsonDocumentOptions options)
{
return JsonDocument.ParseValue(utf8Json, options).RootElement;
}
internal static JsonElement ParseValue(ReadOnlySpan<byte> utf8Json, JsonDocumentOptions options)
{
return JsonDocument.ParseValue(utf8Json, options).RootElement;
}
internal static JsonElement ParseValue(string json, JsonDocumentOptions options)
{
return JsonDocument.ParseValue(json, options).RootElement;
}
public static bool TryParseValue(ref Utf8JsonReader reader, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out JsonElement? element)
{
JsonDocument document;
bool result = JsonDocument.TryParseValue(ref reader, out document, false, false);
element = document?.RootElement;
return result;
}
}
}