protected internal override void ReadEnumerable(JsonSerializerOptions options, ref ReadObjectState current, ref Utf8JsonReader reader) { if (ValueConverter != null) { Type propertyType = PropertyType; if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable <>)) { propertyType = Nullable.GetUnderlyingType(propertyType); } object value = ValueConverter.GetRead(ref reader, propertyType); ReadObjectState.SetReturnValue(value, options, ref current); } else { if (this is IJsonSerializerInternal <TValue> converter) { TValue value = converter.Read(ref reader); ReadObjectState.SetReturnValue(value, options, ref current); } else { throw new InvalidOperationException($"todo: there is no converter for {PropertyType}"); } } }
protected internal override void ReadEnumerable(JsonTokenType tokenType, JsonSerializerOptions options, ref ReadObjectState current, ref Utf8JsonReader reader) { if (ValueConverter != null) { Type propertyType = PropertyType; if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable <>)) { propertyType = Nullable.GetUnderlyingType(propertyType); } if (!ValueConverter.TryRead(propertyType, ref reader, out TValue value)) { throw new JsonReaderException("todo: unable to read value (propertypath)", 0, 0); } ReadObjectState.SetReturnValue(value, options, ref current); } else { if (this is IJsonValueConverter <TValue> converter) { if (!converter.TryRead(PropertyType, ref reader, out TValue value)) { throw new JsonReaderException("todo: unable to read value (propertypath)", 0, 0); } ReadObjectState.SetReturnValue(value, options, ref current); } else { throw new InvalidOperationException($"todo: there is no converter for {PropertyType}"); } } }
private static bool HandleNull(ref ReadObjectState current, JsonSerializerOptions options) { Debug.Assert(current.PropertyInfo != null); JsonPropertyInfo propertyInfo = current.PropertyInfo; if (!propertyInfo.CanBeNull) { throw new InvalidOperationException($"todo: {propertyInfo.PropertyType} can't be null"); } if (current.IsEnumerable() || current.IsPropertyEnumerable()) { ReadObjectState.SetReturnValue(null, options, ref current); return(false); } if (current.ReturnValue == null) { return(true); } if (!propertyInfo.IgnoreNullPropertyValueOnRead(options)) { current.PropertyInfo.SetValueAsObject(current.ReturnValue, null, options); } return(false); }
private static void HandleStartArray( JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadObjectState current, ref List <ReadObjectState> previous, ref int arrayIndex) { Type arrayType = current.PropertyInfo.PropertyType; if (!typeof(IEnumerable).IsAssignableFrom(arrayType) || (arrayType.IsArray && arrayType.GetArrayRank() > 1)) { throw new JsonReaderException($"todo: type {arrayType.ToString()} is not convertable to array.", 0, 0); } Debug.Assert(current.IsPropertyEnumerable()); if (current.IsPropertyEnumerable()) { if (current.EnumerableCreated) { // A nested json array so push a new stack frame. Type elementType = current.ClassInfo.ElementClassInfo.GetPolicyProperty().PropertyType; SetPreviousState(ref previous, current, arrayIndex++); current.Reset(); current.ClassInfo = options.GetOrAddClass(elementType); current.PropertyInfo = current.ClassInfo.GetPolicyProperty(); current.PopStackOnEndArray = true; } else { current.EnumerableCreated = true; } // If current property is already set (from a constructor, for example) leave as-is if (current.PropertyInfo.GetValueAsObject(current.ReturnValue, options) == null) { // Create the enumerable. object value = ReadObjectState.CreateEnumerableValue(ref current, options); if (value != null) { if (current.ReturnValue != null) { current.PropertyInfo.SetValueAsObject(current.ReturnValue, value, options); } else { // Primitive arrays being returned without object current.SetReturnValue(value, options); } } } } }
private static bool HandleEndObject(JsonSerializerOptions options, ref ReadObjectState current, ref List <ReadObjectState> previous, ref int arrayIndex) { object value = current.ReturnValue; if (arrayIndex > 0) { ReadObjectState previousFrame = default; GetPreviousState(ref previous, ref previousFrame, --arrayIndex); current = previousFrame; } else { current.Reset(); current.ReturnValue = value; return(true); } ReadObjectState.SetReturnValue(value, options, ref current); return(false); }
private static bool HandleEndArray( JsonSerializerOptions options, ref ReadObjectState current, ref List <ReadObjectState> previous, ref int arrayIndex) { IEnumerable value = ReadObjectState.GetEnumerableValue(current); if (value == null) { // We added the items to the list property already. current.ResetProperty(); return(false); } bool lastFrame = (arrayIndex == 0); bool setPropertyDirectly; if (current.TempEnumerableValues != null) { JsonEnumerableConverter converter = current.PropertyInfo.EnumerableConverter; if (converter == null) { converter = current.ClassInfo.EnumerableConverter; } Type elementType = current.GetElementType(); value = converter.CreateFromList(elementType, (IList)value); setPropertyDirectly = true; } else { setPropertyDirectly = false; } if (current.PopStackOnEndArray) { ReadObjectState previousFrame = default; GetPreviousState(ref previous, ref previousFrame, --arrayIndex); current = previousFrame; } if (lastFrame) { if (current.ReturnValue == null) { // Returning a converted list or object. current.Reset(); current.ReturnValue = value; return(true); } else if (current.IsEnumerable()) { // Returning a non-converted list. return(true); } // else there must be an outer object, so we'll return false here. } ReadObjectState.SetReturnValue(value, options, ref current, setPropertyDirectly: setPropertyDirectly); return(false); }