private static bool HandleNull(ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options) { if (state.Current.Skip()) { return(false); } JsonPropertyInfo propertyInfo = state.Current.JsonPropertyInfo; if (!propertyInfo.CanBeNull) { ThrowHelper.ThrowJsonReaderException_DeserializeCannotBeNull(reader, state); } if (state.Current.IsEnumerable() || state.Current.IsPropertyEnumerable()) { ReadStackFrame.SetReturnValue(null, options, ref state.Current); return(false); } if (state.Current.ReturnValue == null) { return(true); } if (!propertyInfo.IgnoreNullPropertyValueOnRead(options)) { state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, null, options); } return(false); }
protected override object CreateObject(ref ReadStackFrame frame) { var args = frame.PropertyValueCache; string id = (string)args[nameof(TimeZoneInfo.Id)]; try { TimeZoneInfo ti = TimeZoneInfo.FindSystemTimeZoneById(id); if (ti != null) { return(ti); } } catch (TimeZoneNotFoundException) { } return(TimeZoneInfo.CreateCustomTimeZone( id, (TimeSpan)args[nameof(TimeZoneInfo.BaseUtcOffset)], (string)args[nameof(TimeZoneInfo.DisplayName)], (string)args[nameof(TimeZoneInfo.StandardName)], (string)args[nameof(TimeZoneInfo.DaylightName)], (TimeZoneInfo.AdjustmentRule[])args[nameof(TimeZoneInfo.GetAdjustmentRules)] )); }
private static bool HandleEndObject(JsonSerializerOptions options, ref ReadStack state) { bool isLastFrame = state.IsLastFrame; if (state.Current.Drain) { state.Pop(); return(isLastFrame); } state.Current.JsonClassInfo.UpdateSortedPropertyCache(ref state.Current); object value = state.Current.ReturnValue; if (isLastFrame) { state.Current.Reset(); state.Current.ReturnValue = value; return(true); } state.Pop(); ReadStackFrame.SetReturnValue(value, options, ref state.Current); return(false); }
protected override object CreateObject(ref ReadStackFrame frame) { var createObject = (JsonClassInfo.ParameterizedConstructorDelegate <T, TArg0, TArg1, TArg2, TArg3>) frame.JsonClassInfo.CreateObjectWithArgs !; var arguments = (Arguments <TArg0, TArg1, TArg2, TArg3>)frame.CtorArgumentState !.Arguments; return(createObject !(arguments.Arg0, arguments.Arg1, arguments.Arg2, arguments.Arg3)); }
protected override object CreateObject(ref ReadStackFrame frame) { var args = frame.PropertyValueCache; return(TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule( (DateTime)args[nameof(TimeZoneInfo.AdjustmentRule.DateStart)], (DateTime)args[nameof(TimeZoneInfo.AdjustmentRule.DateEnd)], (TimeSpan)args[nameof(TimeZoneInfo.AdjustmentRule.DaylightDelta)], (TimeZoneInfo.TransitionTime)args[nameof(TimeZoneInfo.AdjustmentRule.DaylightTransitionStart)], (TimeZoneInfo.TransitionTime)args[nameof(TimeZoneInfo.AdjustmentRule.DaylightTransitionEnd)] )); }
protected override object CreateObject(ref ReadStackFrame frame) { object[] arguments = (object[])frame.CtorArgumentState!.Arguments; var createObject = (JsonClassInfo.ParameterizedConstructorDelegate<T>?)frame.JsonClassInfo.CreateObjectWithArgs; if (createObject == null) { // This means this constructor has more than 64 parameters. ThrowHelper.ThrowNotSupportedException_ConstructorMaxOf64Parameters(ConstructorInfo!, TypeToConvert); } object obj = createObject(arguments); ArrayPool<object>.Shared.Return(arguments, clearArray: true); return obj; }
protected override object CreateObject(ref ReadStackFrame frame) { var args = frame.PropertyValueCache; bool isFixedDateRule = (bool)args[nameof(TimeZoneInfo.TransitionTime.IsFixedDateRule)]; if (isFixedDateRule) { return(TimeZoneInfo.TransitionTime.CreateFixedDateRule( (DateTime)args[nameof(TimeZoneInfo.TransitionTime.TimeOfDay)], (int)args[nameof(TimeZoneInfo.TransitionTime.Month)], (int)args[nameof(TimeZoneInfo.TransitionTime.Day)] )); } return(TimeZoneInfo.TransitionTime.CreateFloatingDateRule( (DateTime)args[nameof(TimeZoneInfo.TransitionTime.TimeOfDay)], (int)args[nameof(TimeZoneInfo.TransitionTime.Month)], (int)args[nameof(TimeZoneInfo.TransitionTime.Day)], (DayOfWeek)args[nameof(TimeZoneInfo.TransitionTime.DayOfWeek)] )); }
protected override object CreateObject(ref ReadStackFrame frame) { var arguments = (Arguments <TArg0, TArg1, TArg2, TArg3>)frame.CtorArgumentState !.Arguments !; return(_createObject !(arguments.Arg0, arguments.Arg1, arguments.Arg2, arguments.Arg3) !); }
internal JsonPropertyInfo GetProperty( ReadOnlySpan <byte> propertyName, ref ReadStackFrame frame, out byte[] utf8PropertyName) { PropertyRef propertyRef; ValidateCanBeUsedForMetadataSerialization(); ulong key = GetKey(propertyName); // Keep a local copy of the cache in case it changes by another thread. PropertyRef[]? localPropertyRefsSorted = _propertyRefsSorted; // If there is an existing cache, then use it. if (localPropertyRefsSorted != null) { // Start with the current property index, and then go forwards\backwards. int propertyIndex = frame.PropertyIndex; int count = localPropertyRefsSorted.Length; int iForward = Math.Min(propertyIndex, count); int iBackward = iForward - 1; while (true) { if (iForward < count) { propertyRef = localPropertyRefsSorted[iForward]; if (IsPropertyRefEqual(propertyRef, propertyName, key)) { utf8PropertyName = propertyRef.NameFromJson; return(propertyRef.Info); } ++iForward; if (iBackward >= 0) { propertyRef = localPropertyRefsSorted[iBackward]; if (IsPropertyRefEqual(propertyRef, propertyName, key)) { utf8PropertyName = propertyRef.NameFromJson; return(propertyRef.Info); } --iBackward; } } else if (iBackward >= 0) { propertyRef = localPropertyRefsSorted[iBackward]; if (IsPropertyRefEqual(propertyRef, propertyName, key)) { utf8PropertyName = propertyRef.NameFromJson; return(propertyRef.Info); } --iBackward; } else { // Property was not found. break; } } } // No cached item was found. Try the main dictionary which has all of the properties. #if DEBUG if (PropertyCache == null) { Debug.Fail($"Property cache is null. {GetPropertyDebugInfo(propertyName)}"); } #endif if (PropertyCache !.TryGetValue(JsonHelpers.Utf8GetString(propertyName), out JsonPropertyInfo? info)) { Debug.Assert(info != null, "PropertyCache contains null JsonPropertyInfo"); if (Options.PropertyNameCaseInsensitive) { if (propertyName.SequenceEqual(info.NameAsUtf8Bytes)) { #if DEBUG ulong recomputedKey = GetKey(info.NameAsUtf8Bytes.AsSpan()); if (key != recomputedKey) { string propertyNameStr = JsonHelpers.Utf8GetString(propertyName); Debug.Fail($"key {key} [propertyName={propertyNameStr}] does not match re-computed value {recomputedKey} for the same sequence (case-insensitive). {info.GetDebugInfo()}"); } #endif // Use the existing byte[] reference instead of creating another one. utf8PropertyName = info.NameAsUtf8Bytes !; } else { // Make a copy of the original Span. utf8PropertyName = propertyName.ToArray(); } } else { #if DEBUG ulong recomputedKey = GetKey(info.NameAsUtf8Bytes.AsSpan()); if (key != recomputedKey) { string propertyNameStr = JsonHelpers.Utf8GetString(propertyName); Debug.Fail($"key {key} [propertyName={propertyNameStr}] does not match re-computed value {recomputedKey} for the same sequence (case-sensitive). {info.GetDebugInfo()}"); } #endif utf8PropertyName = info.NameAsUtf8Bytes; } }
internal JsonParameterInfo?GetParameter( ReadOnlySpan <byte> propertyName, ref ReadStackFrame frame, out byte[] utf8PropertyName) { ParameterRef parameterRef; ulong key = GetKey(propertyName); // Keep a local copy of the cache in case it changes by another thread. ParameterRef[]? localParameterRefsSorted = _parameterRefsSorted; // If there is an existing cache, then use it. if (localParameterRefsSorted != null) { // Start with the current parameter index, and then go forwards\backwards. int parameterIndex = frame.CtorArgumentState !.ParameterIndex; int count = localParameterRefsSorted.Length; int iForward = Math.Min(parameterIndex, count); int iBackward = iForward - 1; while (true) { if (iForward < count) { parameterRef = localParameterRefsSorted[iForward]; if (IsParameterRefEqual(parameterRef, propertyName, key)) { utf8PropertyName = parameterRef.NameFromJson; return(parameterRef.Info); } ++iForward; if (iBackward >= 0) { parameterRef = localParameterRefsSorted[iBackward]; if (IsParameterRefEqual(parameterRef, propertyName, key)) { utf8PropertyName = parameterRef.NameFromJson; return(parameterRef.Info); } --iBackward; } } else if (iBackward >= 0) { parameterRef = localParameterRefsSorted[iBackward]; if (IsParameterRefEqual(parameterRef, propertyName, key)) { utf8PropertyName = parameterRef.NameFromJson; return(parameterRef.Info); } --iBackward; } else { // Property was not found. break; } } } // No cached item was found. Try the main dictionary which has all of the parameters. Debug.Assert(ParameterCache != null); if (ParameterCache.TryGetValue(JsonHelpers.Utf8GetString(propertyName), out JsonParameterInfo? info)) { Debug.Assert(info != null); if (Options.PropertyNameCaseInsensitive) { if (propertyName.SequenceEqual(info.NameAsUtf8Bytes)) { Debug.Assert(key == GetKey(info.NameAsUtf8Bytes.AsSpan())); // Use the existing byte[] reference instead of creating another one. utf8PropertyName = info.NameAsUtf8Bytes !; } else { // Make a copy of the original Span. utf8PropertyName = propertyName.ToArray(); } } else { Debug.Assert(key == GetKey(info.NameAsUtf8Bytes !.AsSpan())); utf8PropertyName = info.NameAsUtf8Bytes !; } } else { Debug.Assert(info == null); // Make a copy of the original Span. utf8PropertyName = propertyName.ToArray(); } // Check if we should add this to the cache. // Only cache up to a threshold length and then just use the dictionary when an item is not found in the cache. int cacheCount = 0; if (localParameterRefsSorted != null) { cacheCount = localParameterRefsSorted.Length; } // Do a quick check for the stable (after warm-up) case. if (cacheCount < ParameterNameCountCacheThreshold) { // Do a slower check for the warm-up case. if (frame.CtorArgumentState !.ParameterRefCache != null) { cacheCount += frame.CtorArgumentState.ParameterRefCache.Count; } // Check again to append the cache up to the threshold. if (cacheCount < ParameterNameCountCacheThreshold) { if (frame.CtorArgumentState.ParameterRefCache == null) { frame.CtorArgumentState.ParameterRefCache = new List <ParameterRef>(); } parameterRef = new ParameterRef(key, info !, utf8PropertyName); frame.CtorArgumentState.ParameterRefCache.Add(parameterRef); } } return(info); }
protected abstract object CreateObject(ref ReadStackFrame frame);