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}");
        }
示例#2
0
        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}");
        }