internal static ReadOnlySpan <byte> GetPropertyName( ref ReadStack state, ref Utf8JsonReader reader, JsonSerializerOptions options) { ReadOnlySpan <byte> unescapedPropertyName; ReadOnlySpan <byte> propertyName = reader.GetSpan(); if (reader.ValueIsEscaped) { unescapedPropertyName = JsonReaderHelper.GetUnescapedSpan(propertyName); } else { unescapedPropertyName = propertyName; } if (state.Current.CanContainMetadata) { if (IsMetadataPropertyName(propertyName, state.Current.BaseJsonTypeInfo.PolymorphicTypeResolver)) { ThrowHelper.ThrowUnexpectedMetadataException(propertyName, ref reader, ref state); } } return(unescapedPropertyName); }
internal static ReadOnlySpan <byte> GetPropertyName( ref ReadStack state, ref Utf8JsonReader reader, JsonSerializerOptions options) { ReadOnlySpan <byte> unescapedPropertyName; ReadOnlySpan <byte> propertyName = reader.GetSpan(); if (reader._stringHasEscaping) { int idx = propertyName.IndexOf(JsonConstants.BackSlash); Debug.Assert(idx != -1); unescapedPropertyName = JsonReaderHelper.GetUnescapedSpan(propertyName, idx); } else { unescapedPropertyName = propertyName; } if (state.CanContainMetadata) { if (propertyName.Length > 0 && propertyName[0] == '$') { ThrowHelper.ThrowUnexpectedMetadataException(propertyName, ref reader, ref state); } } return(unescapedPropertyName); }
internal static bool TryReadMetadata(JsonConverter converter, ref Utf8JsonReader reader, ref ReadStack state) { Debug.Assert(state.Current.ObjectState == StackFrameObjectState.StartToken); Debug.Assert(state.CanContainMetadata); while (true) { if (state.Current.PropertyState == StackFramePropertyState.None) { state.Current.PropertyState = StackFramePropertyState.ReadName; // Read the property name. if (!reader.Read()) { return(false); } } if (state.Current.PropertyState < StackFramePropertyState.Name) { if (reader.TokenType == JsonTokenType.EndObject) { // Read the entire object while parsing for metadata. return(true); } // We just read a property. The only valid next tokens are EndObject and PropertyName. Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Ref)) { // No properties whatsoever should follow a $ref property. ThrowHelper.ThrowJsonException_MetadataReferenceObjectCannotContainOtherProperties(reader.GetSpan(), ref state); } ReadOnlySpan <byte> propertyName = reader.GetSpan(); switch (state.Current.LatestMetadataPropertyName = GetMetadataPropertyName(propertyName)) { case MetadataPropertyName.Id: state.Current.JsonPropertyName = s_idPropertyName; if ((state.Current.MetadataPropertyNames & (MetadataPropertyName.Id | MetadataPropertyName.Ref)) != 0) { // No $id or $ref properties should precede $id properties. ThrowHelper.ThrowJsonException_MetadataIdIsNotFirstProperty(propertyName, ref state); } if (!converter.CanHaveMetadata) { // Should not be permitted unless the converter is capable of handling metadata. ThrowHelper.ThrowJsonException_MetadataCannotParsePreservedObjectIntoImmutable(converter.TypeToConvert); } break; case MetadataPropertyName.Ref: state.Current.JsonPropertyName = s_refPropertyName; if (converter.IsValueType) { // Should not be permitted if the converter is a struct. ThrowHelper.ThrowJsonException_MetadataInvalidReferenceToValueType(converter.TypeToConvert); } if (state.Current.MetadataPropertyNames != 0) { // No metadata properties should precede a $ref property. ThrowHelper.ThrowJsonException_MetadataReferenceObjectCannotContainOtherProperties(reader.GetSpan(), ref state); } break; case MetadataPropertyName.Values: state.Current.JsonPropertyName = s_valuesPropertyName; if (state.Current.MetadataPropertyNames == MetadataPropertyName.None) { // Cannot have a $values property unless there are preceding metadata properties. ThrowHelper.ThrowJsonException_MetadataMissingIdBeforeValues(ref state, propertyName); } break; default: Debug.Assert(state.Current.LatestMetadataPropertyName == MetadataPropertyName.None); // Encountered a non-metadata property, exit the reader. return(true); } state.Current.PropertyState = StackFramePropertyState.Name; } if (state.Current.PropertyState < StackFramePropertyState.ReadValue) { state.Current.PropertyState = StackFramePropertyState.ReadValue; // Read the property value. if (!reader.Read()) { return(false); } } Debug.Assert(state.Current.PropertyState == StackFramePropertyState.ReadValue); switch (state.Current.LatestMetadataPropertyName) { case MetadataPropertyName.Id: if (reader.TokenType != JsonTokenType.String) { ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType); } if (state.ReferenceId != null) { ThrowHelper.ThrowNotSupportedException_ObjectWithParameterizedCtorRefMetadataNotSupported(s_refPropertyName, ref reader, ref state); } state.ReferenceId = reader.GetString(); break; case MetadataPropertyName.Ref: if (reader.TokenType != JsonTokenType.String) { ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType); } if (state.ReferenceId != null) { ThrowHelper.ThrowNotSupportedException_ObjectWithParameterizedCtorRefMetadataNotSupported(s_refPropertyName, ref reader, ref state); } state.ReferenceId = reader.GetString(); break; case MetadataPropertyName.Values: if (reader.TokenType != JsonTokenType.StartArray) { ThrowHelper.ThrowJsonException_MetadataValuesInvalidToken(reader.TokenType); } state.Current.PropertyState = StackFramePropertyState.None; state.Current.MetadataPropertyNames |= state.Current.LatestMetadataPropertyName; return(true); // "$values" property contains the nested payload, exit the metadata reader now. default: Debug.Fail("Non-metadata properties should not reach this stage."); break; } state.Current.MetadataPropertyNames |= state.Current.LatestMetadataPropertyName; state.Current.PropertyState = StackFramePropertyState.None; state.Current.JsonPropertyName = null; } }
/// <summary> /// Returns true if successful, false is the reader ran out of buffer. /// Sets state.Current.ReturnValue to the $ref target for MetadataRefProperty cases. /// </summary> internal static bool ResolveMetadata( JsonConverter converter, ref Utf8JsonReader reader, ref ReadStack state) { if (state.Current.ObjectState < StackFrameObjectState.ReadAheadNameOrEndObject) { // Read the first metadata property name. if (!ReadAheadMetataDataAndSetState(ref reader, ref state, StackFrameObjectState.ReadNameOrEndObject)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadNameOrEndObject) { if (reader.TokenType != JsonTokenType.PropertyName) { // An enumerable needs metadata since it starts with StartObject. if (converter.ClassType == ClassType.Enumerable) { ThrowHelper.ThrowJsonException_MetadataPreservedArrayValuesNotFound(converter.TypeToConvert); } // The reader should have detected other invalid cases. Debug.Assert(reader.TokenType == JsonTokenType.EndObject); // Skip the read of the first property name, since we already read it above. state.Current.PropertyState = StackFramePropertyState.ReadName; return(true); } ReadOnlySpan <byte> propertyName = reader.GetSpan(); MetadataPropertyName metadata = GetMetadataPropertyName(propertyName); if (metadata == MetadataPropertyName.Id) { state.Current.JsonPropertyName = propertyName.ToArray(); if (!converter.CanHaveIdMetadata) { ThrowHelper.ThrowJsonException_MetadataCannotParsePreservedObjectIntoImmutable(converter.TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.ReadAheadIdValue; } else if (metadata == MetadataPropertyName.Ref) { state.Current.JsonPropertyName = propertyName.ToArray(); if (converter.IsValueType) { ThrowHelper.ThrowJsonException_MetadataInvalidReferenceToValueType(converter.TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.ReadAheadRefValue; } else if (metadata == MetadataPropertyName.Values) { state.Current.JsonPropertyName = propertyName.ToArray(); if (converter.ClassType == ClassType.Enumerable) { ThrowHelper.ThrowJsonException_MetadataMissingIdBeforeValues(); } else { ThrowHelper.ThrowJsonException_MetadataInvalidPropertyWithLeadingDollarSign(propertyName, ref state, reader); } } else { Debug.Assert(metadata == MetadataPropertyName.NoMetadata); // Having a StartObject without metadata properties is not allowed. if (converter.ClassType == ClassType.Enumerable) { state.Current.JsonPropertyName = propertyName.ToArray(); ThrowHelper.ThrowJsonException_MetadataPreservedArrayInvalidProperty(converter.TypeToConvert, reader); } // Skip the read of the first property name, since we already read it above. state.Current.PropertyState = StackFramePropertyState.ReadName; return(true); } } if (state.Current.ObjectState == StackFrameObjectState.ReadAheadRefValue) { if (!ReadAheadMetataDataAndSetState(ref reader, ref state, StackFrameObjectState.ReadRefValue)) { return(false); } } else if (state.Current.ObjectState == StackFrameObjectState.ReadAheadIdValue) { if (!ReadAheadMetataDataAndSetState(ref reader, ref state, StackFrameObjectState.ReadIdValue)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadRefValue) { if (reader.TokenType != JsonTokenType.String) { ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType); } string key = reader.GetString() !; // todo: https://github.com/dotnet/runtime/issues/32354 state.Current.ReturnValue = state.ReferenceResolver.ResolveReferenceOnDeserialize(key); state.Current.ObjectState = StackFrameObjectState.ReadAheadRefEndObject; } else if (state.Current.ObjectState == StackFrameObjectState.ReadIdValue) { if (reader.TokenType != JsonTokenType.String) { ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType); } state.Current.MetadataId = reader.GetString(); // Clear the MetadataPropertyName since we are done processing Id. state.Current.JsonPropertyName = default; if (converter.ClassType == ClassType.Enumerable) { // Need to Read $values property name. state.Current.ObjectState = StackFrameObjectState.ReadAheadValuesName; } else { // We are done reading metadata. state.Current.ObjectState = StackFrameObjectState.PropertyValue; return(true); } } if (state.Current.ObjectState == StackFrameObjectState.ReadAheadRefEndObject) { if (!ReadAheadMetataDataAndSetState(ref reader, ref state, StackFrameObjectState.ReadRefEndObject)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadRefEndObject) { if (reader.TokenType != JsonTokenType.EndObject) { // We just read a property. The only valid next tokens are EndObject and PropertyName. Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); ThrowHelper.ThrowJsonException_MetadataReferenceObjectCannotContainOtherProperties(reader.GetSpan(), ref state); } return(true); } if (state.Current.ObjectState == StackFrameObjectState.ReadAheadValuesName) { if (!ReadAheadMetataDataAndSetState(ref reader, ref state, StackFrameObjectState.ReadValuesName)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadValuesName) { if (reader.TokenType != JsonTokenType.PropertyName) { ThrowHelper.ThrowJsonException_MetadataPreservedArrayValuesNotFound(converter.TypeToConvert); } ReadOnlySpan <byte> propertyName = reader.GetSpan(); // Remember the property in case we get an exception. state.Current.JsonPropertyName = propertyName.ToArray(); if (GetMetadataPropertyName(propertyName) != MetadataPropertyName.Values) { ThrowHelper.ThrowJsonException_MetadataPreservedArrayInvalidProperty(converter.TypeToConvert, reader); } state.Current.ObjectState = StackFrameObjectState.ReadAheadValuesStartArray; } if (state.Current.ObjectState == StackFrameObjectState.ReadAheadValuesStartArray) { if (!ReadAheadMetataDataAndSetState(ref reader, ref state, StackFrameObjectState.ReadValuesStartArray)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadValuesStartArray) { if (reader.TokenType != JsonTokenType.StartArray) { ThrowHelper.ThrowJsonException_MetadataValuesInvalidToken(reader.TokenType); } state.Current.ObjectState = StackFrameObjectState.PropertyValue; } return(true); }
internal static JsonPropertyInfo LookupProperty( object obj, ref Utf8JsonReader reader, JsonSerializerOptions options, ref ReadStack state, out bool useExtensionProperty) { Debug.Assert(state.Current.JsonClassInfo.ClassType == ClassType.Object); JsonPropertyInfo jsonPropertyInfo; ReadOnlySpan <byte> unescapedPropertyName; ReadOnlySpan <byte> propertyName = reader.GetSpan(); if (reader._stringHasEscaping) { int idx = propertyName.IndexOf(JsonConstants.BackSlash); Debug.Assert(idx != -1); unescapedPropertyName = GetUnescapedString(propertyName, idx); } else { unescapedPropertyName = propertyName; } if (options.ReferenceHandling.ShouldReadPreservedReferences()) { if (propertyName.Length > 0 && propertyName[0] == '$') { ThrowHelper.ThrowUnexpectedMetadataException(propertyName, ref reader, ref state); } } jsonPropertyInfo = state.Current.JsonClassInfo.GetProperty(unescapedPropertyName, ref state.Current); // Increment PropertyIndex so GetProperty() starts with the next property the next time this function is called. state.Current.PropertyIndex++; // Determine if we should use the extension property. if (jsonPropertyInfo == JsonPropertyInfo.s_missingProperty) { JsonPropertyInfo?dataExtProperty = state.Current.JsonClassInfo.DataExtensionProperty; if (dataExtProperty != null) { state.Current.JsonPropertyNameAsString = JsonHelpers.Utf8GetString(unescapedPropertyName); CreateDataExtensionProperty(obj, dataExtProperty); jsonPropertyInfo = dataExtProperty; } state.Current.JsonPropertyInfo = jsonPropertyInfo; useExtensionProperty = true; return(jsonPropertyInfo); } // Support JsonException.Path. Debug.Assert( jsonPropertyInfo.JsonPropertyName == null || options.PropertyNameCaseInsensitive || unescapedPropertyName.SequenceEqual(jsonPropertyInfo.JsonPropertyName)); state.Current.JsonPropertyInfo = jsonPropertyInfo; if (jsonPropertyInfo.JsonPropertyName == null) { byte[] propertyNameArray = unescapedPropertyName.ToArray(); if (options.PropertyNameCaseInsensitive) { // Each payload can have a different name here; remember the value on the temporary stack. state.Current.JsonPropertyName = propertyNameArray; } else { // Prevent future allocs by caching globally on the JsonPropertyInfo which is specific to a Type+PropertyName // so it will match the incoming payload except when case insensitivity is enabled (which is handled above). state.Current.JsonPropertyInfo.JsonPropertyName = propertyNameArray; } } state.Current.JsonPropertyInfo = jsonPropertyInfo; useExtensionProperty = false; return(jsonPropertyInfo); }
/// <summary> /// Returns true if successful, false is the reader ran out of buffer. /// Sets state.Current.ReturnValue to the reference target for $ref cases; /// Sets state.Current.ReturnValue to a new instance for $id cases. /// </summary> internal static bool ResolveMetadataForJsonObject <T>( ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options) { JsonConverter converter = state.Current.JsonTypeInfo.PropertyInfoForTypeInfo.ConverterBase; if (state.Current.ObjectState < StackFrameObjectState.ReadAheadNameOrEndObject) { // Read the first metadata property name. if (!TryReadAheadMetadataAndSetState(ref reader, ref state, StackFrameObjectState.ReadNameOrEndObject)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadNameOrEndObject) { if (reader.TokenType != JsonTokenType.PropertyName) { // Since this was an empty object, we are done reading metadata. state.Current.ObjectState = StackFrameObjectState.PropertyValue; // Skip the read of the first property name, since we already read it above. state.Current.PropertyState = StackFramePropertyState.ReadName; return(true); } ReadOnlySpan <byte> propertyName = reader.GetSpan(); MetadataPropertyName metadata = GetMetadataPropertyName(propertyName); if (metadata == MetadataPropertyName.Id) { state.Current.JsonPropertyName = s_idPropertyName; if (!converter.CanHaveIdMetadata) { ThrowHelper.ThrowJsonException_MetadataCannotParsePreservedObjectIntoImmutable(converter.TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.ReadAheadIdValue; } else if (metadata == MetadataPropertyName.Ref) { state.Current.JsonPropertyName = s_refPropertyName; if (converter.IsValueType) { ThrowHelper.ThrowJsonException_MetadataInvalidReferenceToValueType(converter.TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.ReadAheadRefValue; } else if (metadata == MetadataPropertyName.Values) { ThrowHelper.ThrowJsonException_MetadataInvalidPropertyWithLeadingDollarSign(propertyName, ref state, reader); } else { Debug.Assert(metadata == MetadataPropertyName.NoMetadata); // We are done reading metadata, the object didn't contain any. state.Current.ObjectState = StackFrameObjectState.PropertyValue; // Skip the read of the first property name, since we already read it above. state.Current.PropertyState = StackFramePropertyState.ReadName; return(true); } } if (state.Current.ObjectState == StackFrameObjectState.ReadAheadRefValue) { if (!TryReadAheadMetadataAndSetState(ref reader, ref state, StackFrameObjectState.ReadRefValue)) { return(false); } } else if (state.Current.ObjectState == StackFrameObjectState.ReadAheadIdValue) { if (!TryReadAheadMetadataAndSetState(ref reader, ref state, StackFrameObjectState.ReadIdValue)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadRefValue) { if (reader.TokenType != JsonTokenType.String) { ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType); } string referenceId = reader.GetString() !; object value = state.ReferenceResolver.ResolveReference(referenceId); ValidateValueIsCorrectType <T>(value, referenceId); state.Current.ReturnValue = value; state.Current.ObjectState = StackFrameObjectState.ReadAheadRefEndObject; } else if (state.Current.ObjectState == StackFrameObjectState.ReadIdValue) { if (reader.TokenType != JsonTokenType.String) { ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType); } converter.CreateInstanceForReferenceResolver(ref reader, ref state, options); string referenceId = reader.GetString() !; state.ReferenceResolver.AddReference(referenceId, state.Current.ReturnValue !); // We are done reading metadata plus we instantiated the object. state.Current.ObjectState = StackFrameObjectState.CreatedObject; } // Clear the metadata property name that was set in case of failure on ResolveReference/AddReference. state.Current.JsonPropertyName = null; if (state.Current.ObjectState == StackFrameObjectState.ReadAheadRefEndObject) { if (!TryReadAheadMetadataAndSetState(ref reader, ref state, StackFrameObjectState.ReadRefEndObject)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadRefEndObject) { if (reader.TokenType != JsonTokenType.EndObject) { // We just read a property. The only valid next tokens are EndObject and PropertyName. Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); ThrowHelper.ThrowJsonException_MetadataReferenceObjectCannotContainOtherProperties(reader.GetSpan(), ref state); } } return(true); }
/// <summary> /// Returns true if successful, false is the reader ran out of buffer. /// Sets state.Current.ReturnValue to the reference target for $ref cases; /// Sets state.Current.ReturnValue to a new instance for $id cases. /// </summary> internal static bool ResolveMetadataForJsonArray <T>( ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options) { JsonConverter converter = state.Current.JsonTypeInfo.PropertyInfoForTypeInfo.ConverterBase; if (state.Current.ObjectState < StackFrameObjectState.ReadAheadNameOrEndObject) { // Read the first metadata property name. if (!TryReadAheadMetadataAndSetState(ref reader, ref state, StackFrameObjectState.ReadNameOrEndObject)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadNameOrEndObject) { if (reader.TokenType != JsonTokenType.PropertyName) { // The reader should have detected other invalid cases. Debug.Assert(reader.TokenType == JsonTokenType.EndObject); // An enumerable needs metadata since it starts with StartObject. ThrowHelper.ThrowJsonException_MetadataPreservedArrayValuesNotFound(ref state, converter.TypeToConvert); } ReadOnlySpan <byte> propertyName = reader.GetSpan(); MetadataPropertyName metadata = GetMetadataPropertyName(propertyName); if (metadata == MetadataPropertyName.Id) { state.Current.JsonPropertyName = s_idPropertyName; if (!converter.CanHaveIdMetadata) { ThrowHelper.ThrowJsonException_MetadataCannotParsePreservedObjectIntoImmutable(converter.TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.ReadAheadIdValue; } else if (metadata == MetadataPropertyName.Ref) { state.Current.JsonPropertyName = s_refPropertyName; if (converter.IsValueType) { ThrowHelper.ThrowJsonException_MetadataInvalidReferenceToValueType(converter.TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.ReadAheadRefValue; } else if (metadata == MetadataPropertyName.Values) { ThrowHelper.ThrowJsonException_MetadataMissingIdBeforeValues(ref state, propertyName); } else { Debug.Assert(metadata == MetadataPropertyName.NoMetadata); // Having a StartObject without metadata properties is not allowed. ThrowHelper.ThrowJsonException_MetadataPreservedArrayInvalidProperty(ref state, converter.TypeToConvert, reader); } } if (state.Current.ObjectState == StackFrameObjectState.ReadAheadRefValue) { if (!TryReadAheadMetadataAndSetState(ref reader, ref state, StackFrameObjectState.ReadRefValue)) { return(false); } } else if (state.Current.ObjectState == StackFrameObjectState.ReadAheadIdValue) { if (!TryReadAheadMetadataAndSetState(ref reader, ref state, StackFrameObjectState.ReadIdValue)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadRefValue) { if (reader.TokenType != JsonTokenType.String) { ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType); } string referenceId = reader.GetString() !; object value = state.ReferenceResolver.ResolveReference(referenceId); ValidateValueIsCorrectType <T>(value, referenceId); state.Current.ReturnValue = value; state.Current.ObjectState = StackFrameObjectState.ReadAheadRefEndObject; } else if (state.Current.ObjectState == StackFrameObjectState.ReadIdValue) { if (reader.TokenType != JsonTokenType.String) { ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType); } converter.CreateInstanceForReferenceResolver(ref reader, ref state, options); string referenceId = reader.GetString() !; state.ReferenceResolver.AddReference(referenceId, state.Current.ReturnValue !); // Need to Read $values property name. state.Current.ObjectState = StackFrameObjectState.ReadAheadValuesName; } // Clear the metadata property name that was set in case of failure on ResolverReference/AddReference. state.Current.JsonPropertyName = null; if (state.Current.ObjectState == StackFrameObjectState.ReadAheadRefEndObject) { if (!TryReadAheadMetadataAndSetState(ref reader, ref state, StackFrameObjectState.ReadRefEndObject)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadRefEndObject) { if (reader.TokenType != JsonTokenType.EndObject) { // We just read a property. The only valid next tokens are EndObject and PropertyName. Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); ThrowHelper.ThrowJsonException_MetadataReferenceObjectCannotContainOtherProperties(reader.GetSpan(), ref state); } return(true); } if (state.Current.ObjectState == StackFrameObjectState.ReadAheadValuesName) { if (!TryReadAheadMetadataAndSetState(ref reader, ref state, StackFrameObjectState.ReadValuesName)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadValuesName) { if (reader.TokenType != JsonTokenType.PropertyName) { ThrowHelper.ThrowJsonException_MetadataPreservedArrayValuesNotFound(ref state, converter.TypeToConvert); } ReadOnlySpan <byte> propertyName = reader.GetSpan(); if (GetMetadataPropertyName(propertyName) != MetadataPropertyName.Values) { ThrowHelper.ThrowJsonException_MetadataPreservedArrayInvalidProperty(ref state, converter.TypeToConvert, reader); } // Remember the property in case we get an exception in one of the array elements. state.Current.JsonPropertyName = s_valuesPropertyName; state.Current.ObjectState = StackFrameObjectState.ReadAheadValuesStartArray; } if (state.Current.ObjectState == StackFrameObjectState.ReadAheadValuesStartArray) { if (!TryReadAheadMetadataAndSetState(ref reader, ref state, StackFrameObjectState.ReadValuesStartArray)) { return(false); } } if (state.Current.ObjectState == StackFrameObjectState.ReadValuesStartArray) { if (reader.TokenType != JsonTokenType.StartArray) { ThrowHelper.ThrowJsonException_MetadataValuesInvalidToken(reader.TokenType); } state.Current.ValidateEndTokenOnArray = true; state.Current.ObjectState = StackFrameObjectState.CreatedObject; } return(true); }