示例#1
0
 public ExpandClauseParser(IOpenApiTypeHandler binder, string value,
                           IDictionary <PropertyInfo, ExpandClause> clauses, ModelStateDictionary modelStateDictionary)
 {
     _parser  = new QueryExpressionParser(value, binder);
     _clauses = clauses;
     _modelStateDictionary = modelStateDictionary;
 }
示例#2
0
        public static object ReadObject(
            JsonElement obj,
            IOpenApiType itemType,
            Type itemClrType,
            IOpenApiTypeHandler typeHandler,
            bool objectAsDelta = false)
        {
            if (itemType == null)
            {
                throw new SerializationException("Cannot deserialize unknown type.");
            }

            var properties = obj.EnumerateObject().ToDictionary(p => p.Name, p => p.Value);

            if (properties.TryGetValue("@odata.type", out var type) && type.ValueKind == JsonValueKind.String)
            {
                var typeName   = type.GetString();
                var actualType = typeHandler.ResolveType(typeName);
                if (actualType == null)
                {
                    throw new SerializationException($"No type with identifier '{typeName}' found");
                }

                if (!itemClrType.IsAssignableFrom(actualType.ClrType))
                {
                    throw new SerializationException($"Type '{typeName}' is not assignable to '{itemType.JsonName}'");
                }

                itemType    = actualType;
                itemClrType = actualType.ClrType;
            }

            var instance = objectAsDelta
                ? Activator.CreateInstance(typeof(Delta <>).MakeGenericType(itemClrType))
                : Activator.CreateInstance(itemClrType);

            foreach (var member in properties)
            {
                if (itemType.TryGetProperty(member.Key, out var property))
                {
                    var propertyType = typeHandler.ResolveType(property.ClrProperty.PropertyType);

                    var value = ReadValue(member.Value,
                                          propertyType,
                                          property.ClrProperty.PropertyType,
                                          typeHandler,
                                          objectAsDelta);
                    // TODO: check for components in the model binding area which help us here
                    // many conversions (string -> enum,date,timespan) etc. do not work like this.
                    property.SetValue(instance, value);
                }
                else
                {
                    // TODO: how do we want to treat unknown props? fail or ignore?
                }
            }

            return(instance);
        }
示例#3
0
        public static void WriteArray(
            Utf8JsonWriter writer,
            IEnumerable resultItems,
            IOpenApiType itemType,
            SelectClause selectClause,
            IOpenApiTypeHandler typeHandler,
            JsonSerializerOptions options)
        {
            writer.WriteStartArray();

            foreach (var item in resultItems)
            {
                WriteValue(writer, itemType, item, selectClause, typeHandler, options);
            }

            writer.WriteEndArray();
        }
示例#4
0
        public static void WriteObject(
            Utf8JsonWriter writer,
            IOpenApiType itemType,
            object item,
            SelectClause selectClause,
            IOpenApiTypeHandler typeHandler,
            JsonSerializerOptions options)
        {
            if (item == null)
            {
                writer.WriteNullValue();
            }
            else
            {
                writer.WriteStartObject();

                var actualType = typeHandler.ResolveType(item.GetType());
                var needsType  = itemType == null || !itemType.Equals(actualType);
                if (needsType)
                {
                    writer.WriteString("@odata.type", actualType.JsonName);
                }

                foreach (var property in actualType.Properties)
                {
                    SelectClause subClause = null;
                    if (selectClause == null ||
                        selectClause.SelectClauses?.TryGetValue(property.ClrProperty, out subClause) == true ||
                        selectClause.IsStarSelect)
                    {
                        var key = options.PropertyNamingPolicy.ConvertName(property.JsonName);
                        writer.WritePropertyName(JsonEncodedText.Encode(key));

                        WriteValue(writer,
                                   typeHandler.ResolveType(property.ClrProperty.PropertyType),
                                   property.GetValue(item),
                                   subClause,
                                   typeHandler,
                                   options);
                    }
                }

                writer.WriteEndObject();
            }
        }
示例#5
0
        public static object ReadValue(
            JsonElement value,
            IOpenApiType valueType,
            Type valueClrType,
            IOpenApiTypeHandler typeHandler,
            bool objectsAsDelta = false)
        {
            switch (value.ValueKind)
            {
            case JsonValueKind.Object:
                if (valueType == null &&
                    ReflectionHelper.ImplementsDictionary(valueClrType, out var dictKeyType, out var dictValueType))
                {
                    var dictionary = Activator.CreateInstance(valueClrType);
                    var indexer    = valueClrType.GetProperties()
                                     .FirstOrDefault(p => IsDictionaryIndexer(p, dictKeyType, dictValueType));
                    if (indexer == null)
                    {
                        throw new SerializationException(
                                  "Could not find dictionary indexer for deserializing object");
                    }

                    var dictValueApiType = typeHandler.ResolveType(dictValueType);
                    foreach (var prop in value.EnumerateObject())
                    {
                        var dictValue = ReadValue(prop.Value,
                                                  dictValueApiType,
                                                  dictValueType,
                                                  typeHandler,
                                                  false);

                        indexer.SetValue(dictionary,
                                         dictValue,
                                         new object[]
                        {
                            prop.Name
                        });
                    }

                    return(dictionary);
                }
                else
                {
                    return(ReadObject(value, valueType, valueClrType, typeHandler, objectsAsDelta));
                }
示例#6
0
        protected T Deserialize <T>(string json, IOpenApiTypeHandler typeHandler = null)
        {
            if (typeHandler == null)
            {
                typeHandler = new DefaultOpenApiTypeHandler();
            }
            var jsonSerializerOptions = new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                Converters           =
                {
                    new OpenApiQueryDeltaConverterFactory(typeHandler),
                    new OpenApiQueryResultConverterFactory(typeHandler),
                    new OpenApiQuerySingleResultConverterFactory(typeHandler)
                }
            };

            return(JsonSerializer.Deserialize <T>(json, jsonSerializerOptions));
        }
示例#7
0
        public static void WriteDictionary(
            Utf8JsonWriter writer,
            IDictionary value,
            IOpenApiType valueType,
            IOpenApiTypeHandler typeHandler,
            JsonSerializerOptions options)
        {
            writer.WriteStartObject();

            foreach (DictionaryEntry dictionaryEntry in value)
            {
                var key = options.DictionaryKeyPolicy != null
                    ? options.DictionaryKeyPolicy.ConvertName(dictionaryEntry.Key.ToString())
                    : dictionaryEntry.Key.ToString();

                writer.WritePropertyName(JsonEncodedText.Encode(key));

                WriteValue(writer, valueType, dictionaryEntry.Value, null, typeHandler, options);
            }

            writer.WriteEndObject();
        }
示例#8
0
 public OpenApiQueryResultConverterFactory(IOpenApiTypeHandler typeHandler)
 {
     _typeHandler = typeHandler;
 }
 public OpenApiQuerySingleResultConverter(IOpenApiTypeHandler typeHandler)
 {
     _typeHandler = typeHandler;
 }
示例#10
0
 public OpenApiOptionsSetup(IOpenApiTypeHandler typeHandler)
 {
     _typeHandler = typeHandler;
 }
示例#11
0
 public SelectClauseParser(IOpenApiTypeHandler binder, string value)
 {
     _parser = new QueryExpressionParser(value, binder);
 }
示例#12
0
 public QueryExpressionParser(string raw, IOpenApiTypeHandler binder)
 {
     _value  = raw;
     _binder = binder;
     Init();
 }
示例#13
0
 public OrderByClauseParser(IOpenApiTypeHandler binder, string value, IList <OrderByClause> clauses)
 {
     _parser  = new QueryExpressionParser(value, binder);
     _clauses = clauses;
 }
示例#14
0
 public OpenApiQueryApplyResultConverter(IOpenApiTypeHandler typeHandler)
 {
     _typeHandler = typeHandler;
 }
示例#15
0
 public OpenApiQueryDeltaConverterFactory(IOpenApiTypeHandler typeHandler)
 {
     _typeHandler = typeHandler;
 }
示例#16
0
        public static void WriteValue(
            Utf8JsonWriter writer,
            IOpenApiType itemType,
            object item,
            SelectClause subClause,
            IOpenApiTypeHandler typeHandler,
            JsonSerializerOptions options)
        {
            switch (item)
            {
            // we must handle dictionaries, enumerables etc on our own for proper nested object handling
            // maybe we find a better way to utilize the JsonSerializer.Serialize directly without loosing the proper type handling
            case string s:
                // string is an IEnumerable and needs to be handled special to avoid serialization as array
                writer.WriteStringValue(s);
                break;

            case Delta d:
                JsonSerializer.Serialize(writer, d, d.GetType(), options);
                break;

            case IDictionary c:
                if (ReflectionHelper.ImplementsDictionary(c.GetType(), out _, out var valueType))
                {
                    WriteDictionary(writer,
                                    c,
                                    typeHandler.ResolveType(valueType), // use static types for polymorphism
                                    typeHandler,
                                    options);
                }
                else
                {
                    WriteDictionary(writer, c, null, typeHandler, options);
                }

                break;

            case IEnumerable v:
                if (ReflectionHelper.ImplementsEnumerable(v.GetType(), out var enumerableItemType))
                {
                    WriteArray(writer,
                               v,
                               typeHandler.ResolveType(enumerableItemType),
                               subClause,
                               typeHandler,
                               options);
                }
                else
                {
                    WriteArray(writer, v, null, subClause, typeHandler, options);
                }

                break;

            default:
                if (itemType == null)
                {
                    // not handled by OpenApiQuery
                    JsonSerializer.Serialize(writer, item, options);
                }
                else
                {
                    WriteObject(writer, itemType, item, subClause, typeHandler, options);
                }

                break;
            }
        }