protected override void ReadObjectProperties(JsonReader reader, DynamicObject result, Dictionary <string, Property> properties, JsonSerializer serializer) { reader.Advance(); TypeInfo?typeInfo = null; void SetResult(IEnumerable <DynamicProperty>?properties = null) { reader.AssertEndObject(); result.Type = typeInfo; if (properties?.Any() == true) { result.Properties = new PropertySet(properties); } } if (reader.IsProperty(nameof(DynamicObject.Type))) { typeInfo = reader.Read <TypeInfo?>(serializer); reader.Advance(); } if (reader.IsProperty("Value")) { var value = reader.Read(typeInfo, serializer); SetResult(new[] { new DynamicProperty(string.Empty, value) }); return; } if (reader.IsProperty("Values")) { reader.Advance(); if (reader.TokenType == JsonToken.Null) { SetResult(); return; } if (reader.TokenType != JsonToken.StartArray) { throw reader.CreateException($"Expected array"); } var elementType = TypeHelper.GetElementType(typeInfo?.Type) ?? typeof(object); bool TryReadNextItem(out object?value) { if (!reader.TryRead(elementType, serializer, out value)) { // TODO: is max length quota required? if (reader.TokenType == JsonToken.EndArray) { return(false); } throw reader.CreateException("Unexpected token structure."); } return(true); } var values = new List <object?>(); while (TryReadNextItem(out var item)) { values.Add(item); } if (values.Any(x => x != null && (elementType == typeof(object) || !elementType.IsAssignableFrom(x.GetType()))) && values.All(x => x is null || x is string)) { elementType = typeof(string); } var valueArray = CastCollectionToArrayOfType(elementType, values); SetResult(new[] { new DynamicProperty(string.Empty, valueArray) }); return; } if (reader.IsProperty(nameof(DynamicObject.Properties))) { reader.Advance(); if (reader.TokenType == JsonToken.Null) { SetResult(); return; } if (reader.TokenType != JsonToken.StartArray) { throw reader.CreateException("Expected array"); } var propertySet = new List <DynamicProperty>(); bool NextItem() { // TODO: is max length quota required? reader.Advance(); return(reader.TokenType != JsonToken.EndArray); } while (NextItem()) { reader.AssertStartObject(false); reader.AssertProperty(nameof(DynamicProperty.Name)); var name = reader.ReadAsString() ?? throw reader.CreateException("Property name must not be null"); reader.AssertProperty(nameof(Type)); var type = reader.Read <TypeInfo?>(serializer); reader.AssertProperty(nameof(DynamicProperty.Value)); var value = reader.Read(type, serializer); reader.AssertEndObject(); propertySet.Add(new DynamicProperty(name, value)); } SetResult(propertySet); return; } throw reader.CreateException($"Unexpected token {reader.TokenType}"); }
protected override void ReadObjectProperties(JsonReader reader, DynamicObject result, Dictionary <string, Property> properties, JsonSerializer serializer) { reader.CheckNotNull(nameof(reader)).Advance(); result.CheckNotNull(nameof(result)); serializer.CheckNotNull(nameof(serializer)); TypeInfo?typeInfo = null; void SetResult(IEnumerable <DynamicProperty>?properties = null) { reader.AssertEndObject(); result.Type = typeInfo; if (properties?.Any() is true) { result.Properties = new PropertySet(properties); } } if (reader.IsProperty(nameof(DynamicObject.Type))) { typeInfo = reader.Read <TypeInfo?>(serializer); reader.Advance(); } bool IsProperty(string property, out bool isDynamicValueType) { isDynamicValueType = false; if (reader.IsProperty(property)) { return(true); } if (reader.IsProperty($"Dynamic{property}")) { isDynamicValueType = true; return(true); } return(false); } if (IsProperty(ValueProperty, out var isDynamicValue)) { var value = isDynamicValue ? reader.Read <DynamicObject>(serializer) : reader.Read(typeInfo, serializer); SetResult(new[] { new DynamicProperty(string.Empty, value) }); return; } if (IsProperty(ValuesProperty, out isDynamicValue)) { reader.Advance(); if (reader.TokenType == JsonToken.Null) { SetResult(); return; } if (reader.TokenType != JsonToken.StartArray) { throw reader.CreateException($"Expected array"); } var elementType = TypeHelper.GetElementType(typeInfo?.ToType()) ?? typeof(object); bool TryReadNextItem(out object?value) { var itemType = isDynamicValue ? typeof(DynamicObject) : elementType; if (!reader.TryRead(itemType, serializer, out value)) { if (reader.TokenType == JsonToken.EndArray) { return(false); } throw reader.CreateException("Unexpected token structure."); } return(true); } var values = new List <object?>(); while (TryReadNextItem(out var item)) { values.Add(item); } if (isDynamicValue) { elementType = typeof(object); } else if (values.Any(x => x is not null && (elementType == typeof(object) || !elementType.IsInstanceOfType(x))) && values.All(x => x is null || x is string)) { elementType = typeof(string); } var valueArray = values.CastCollectionToArrayOfType(elementType); SetResult(new[] { new DynamicProperty(string.Empty, valueArray) }); return; } if (reader.IsProperty(nameof(DynamicObject.Properties))) { reader.Advance(); if (reader.TokenType == JsonToken.Null) { SetResult(); return; } if (reader.TokenType != JsonToken.StartArray) { throw reader.CreateException("Expected array"); } var propertySet = new List <DynamicProperty>(); bool NextItem() { reader.Advance(); return(reader.TokenType != JsonToken.EndArray); } while (NextItem()) { reader.AssertStartObject(false); reader.AssertProperty(nameof(DynamicProperty.Name)); var name = reader.ReadAsString() ?? throw reader.CreateException("Property name must not be null"); reader.AssertProperty(nameof(Type)); var type = reader.Read <TypeInfo?>(serializer); reader.AssertProperty(nameof(DynamicProperty.Value)); var value = reader.Read(type, serializer); reader.AssertEndObject(); propertySet.Add(new DynamicProperty(name, value)); } SetResult(propertySet); return; } throw reader.CreateException($"Unexpected token {reader.TokenType}"); }