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 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 = JsonReaderHelper.GetUnescapedSpan(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); }