private OpenApiSchema GenerateArraySchema(SerializerMetadata serializerMetadata, SchemaRepository schemaRepository) { return(new OpenApiSchema { Type = "array", Items = GenerateSchema(serializerMetadata.ArrayItemType, schemaRepository), UniqueItems = serializerMetadata.Type.IsSet() ? (bool?)true : null }); }
private OpenApiSchema GenerateReferencedSchema(SerializerMetadata serializerMetadata, SchemaRepository schemaRepository) { return(schemaRepository.GetOrAdd( serializerMetadata.Type, _generatorOptions.SchemaIdSelector(serializerMetadata.Type), () => { var schema = GenerateInlineSchema(serializerMetadata, schemaRepository); ApplyFilters(schema, serializerMetadata.Type, schemaRepository); return schema; })); }
private OpenApiSchema GeneratePrimitiveSchema(SerializerMetadata serializerMetadata) { var schema = new OpenApiSchema { Type = serializerMetadata.DataType, Format = serializerMetadata.DataFormat }; if (serializerMetadata.EnumValues != null) { schema.Enum = serializerMetadata.EnumValues .Select(value => OpenApiAnyFactory.CreateFor(schema, value)) .ToList(); } return(schema); }
private OpenApiSchema GenerateDictionarySchema(SerializerMetadata serializerMetadata, SchemaRepository schemaRepository) { if (serializerMetadata.DictionaryKeyType.IsEnum) { // This is a special case where we can include named properties based on the enum values return(new OpenApiSchema { Type = "object", Properties = serializerMetadata.DictionaryKeyType.GetEnumNames() .ToDictionary( name => name, name => GenerateSchema(serializerMetadata.DictionaryValueType, schemaRepository) ) }); } return(new OpenApiSchema { Type = "object", AdditionalPropertiesAllowed = true, AdditionalProperties = GenerateSchema(serializerMetadata.DictionaryValueType, schemaRepository) }); }
private OpenApiSchema GenerateInlineSchema(SerializerMetadata serializerMetadata, SchemaRepository schemaRepository) { if (serializerMetadata.IsPrimitive) { return(GeneratePrimitiveSchema(serializerMetadata)); } if (serializerMetadata.IsDictionary) { return(GenerateDictionarySchema(serializerMetadata, schemaRepository)); } if (serializerMetadata.IsArray) { return(GenerateArraySchema(serializerMetadata, schemaRepository)); } if (serializerMetadata.IsObject) { return(GenerateObjectSchema(serializerMetadata, schemaRepository)); } return(new OpenApiSchema()); }
public SerializerMetadata GetSerializerMetadataForType(Type type) { var underlyingType = type.IsNullable(out Type innerType) ? innerType : type; if (PrimitiveTypesAndFormats.ContainsKey(underlyingType)) { var primitiveTypeAndFormat = PrimitiveTypesAndFormats[underlyingType]; return(SerializerMetadata.ForPrimitive(underlyingType, primitiveTypeAndFormat.Item1, primitiveTypeAndFormat.Item2)); } if (underlyingType.IsEnum) { var enumValues = GetSerializeEnumValuesFor(underlyingType); var primitiveTypeAndFormat = (enumValues.Any(value => value.GetType() == typeof(string))) ? PrimitiveTypesAndFormats[typeof(string)] : PrimitiveTypesAndFormats[underlyingType.GetEnumUnderlyingType()]; return(SerializerMetadata.ForPrimitive(underlyingType, primitiveTypeAndFormat.Item1, primitiveTypeAndFormat.Item2, enumValues)); } if (underlyingType.IsDictionary(out Type keyType, out Type valueType)) { return(SerializerMetadata.ForDictionary(underlyingType, keyType, valueType)); } if (underlyingType.IsEnumerable(out Type itemType)) { return(SerializerMetadata.ForArray(underlyingType, itemType)); } return(SerializerMetadata.ForObject( underlyingType, GetSerializerPropertiesFor(underlyingType, out Type extensionDataValueType), extensionDataValueType)); }
private OpenApiSchema GenerateObjectSchema(SerializerMetadata serializerMetadata, SchemaRepository schemaRepository) { if (serializerMetadata.Properties == null) { return(new OpenApiSchema { Type = "object" }); } var schema = new OpenApiSchema { Type = "object", Properties = new Dictionary <string, OpenApiSchema>(), Required = new SortedSet <string>() }; // If it's a baseType with known subTypes, add the discriminator property if (_generatorOptions.GeneratePolymorphicSchemas && _generatorOptions.SubTypesResolver(serializerMetadata.Type).Any()) { var discriminatorName = _generatorOptions.DiscriminatorSelector(serializerMetadata.Type); if (!schema.Properties.ContainsKey(discriminatorName)) { schema.Properties.Add(discriminatorName, new OpenApiSchema { Type = "string" }); } schema.Required.Add(discriminatorName); schema.Discriminator = new OpenApiDiscriminator { PropertyName = discriminatorName }; } foreach (var serializerPropertyMetadata in serializerMetadata.Properties) { var customAttributes = serializerPropertyMetadata.MemberInfo?.GetInlineOrMetadataTypeAttributes() ?? Enumerable.Empty <object>(); if (_generatorOptions.IgnoreObsoleteProperties && customAttributes.OfType <ObsoleteAttribute>().Any()) { continue; } var propertySchema = GenerateSchema(serializerPropertyMetadata.MemberType, schemaRepository, memberInfo: serializerPropertyMetadata.MemberInfo); schema.Properties.Add(serializerPropertyMetadata.Name, propertySchema); if (serializerPropertyMetadata.IsRequired || customAttributes.OfType <RequiredAttribute>().Any()) { schema.Required.Add(serializerPropertyMetadata.Name); } if (propertySchema.Reference == null) { propertySchema.Nullable = propertySchema.Nullable && serializerPropertyMetadata.AllowNull; } } if (serializerMetadata.ExtensionDataValueType != null) { schema.AdditionalProperties = GenerateSchema(serializerMetadata.ExtensionDataValueType, schemaRepository); } // If it's a known subType, reference the baseType for inheritied properties if (_generatorOptions.GeneratePolymorphicSchemas && (serializerMetadata.Type.BaseType != null) && _generatorOptions.SubTypesResolver(serializerMetadata.Type.BaseType).Contains(serializerMetadata.Type)) { var baseSerializerContract = _serializerMetadataResolver.GetSerializerMetadataForType(serializerMetadata.Type.BaseType); var baseSchemaReference = GenerateReferencedSchema(baseSerializerContract, schemaRepository); var baseSchema = schemaRepository.Schemas[baseSchemaReference.Reference.Id]; foreach (var basePropertyName in baseSchema.Properties.Keys) { schema.Properties.Remove(basePropertyName); } return(new OpenApiSchema { AllOf = new List <OpenApiSchema> { baseSchemaReference, schema } }); } return(schema); }