private OpenApiSchema GenerateArraySchema(SerializerContract serializerContract, SchemaRepository schemaRepository) { return(new OpenApiSchema { Type = "array", Items = GenerateSchema(serializerContract.ArrayItemType, schemaRepository), UniqueItems = serializerContract.Type.IsSet() ? (bool?)true : null }); }
private OpenApiSchema GenerateReferencedSchema(SerializerContract serializerContract, SchemaRepository schemaRepository) { return(schemaRepository.GetOrAdd( serializerContract.Type, _generatorOptions.SchemaIdSelector(serializerContract.Type), () => { var schema = GenerateInlineSchema(serializerContract, schemaRepository); ApplyFilters(schema, serializerContract.Type, schemaRepository); return schema; })); }
private OpenApiSchema GeneratePrimitiveSchema(SerializerContract serializerContract) { var schema = new OpenApiSchema { Type = serializerContract.DataType, Format = serializerContract.DataFormat }; if (serializerContract.EnumValues != null) { schema.Enum = serializerContract.EnumValues .Select(value => OpenApiAnyFactory.CreateFor(schema, value)) .ToList(); } return(schema); }
private OpenApiSchema GenerateDictionarySchema(SerializerContract serializerContract, SchemaRepository schemaRepository) { if (serializerContract.DictionaryKeyType.IsEnum) { // This is a special case where we can include named properties based on the enum values return(new OpenApiSchema { Type = "object", Properties = serializerContract.DictionaryKeyType.GetEnumNames() .ToDictionary( name => name, name => GenerateSchema(serializerContract.DictionaryValueType, schemaRepository) ) }); } return(new OpenApiSchema { Type = "object", AdditionalPropertiesAllowed = true, AdditionalProperties = GenerateSchema(serializerContract.DictionaryValueType, schemaRepository) }); }
public SerializerContract GetSerializerContractForType(Type type) { var underlyingType = type.IsNullable(out Type innerType) ? innerType : type; if (PrimitiveTypesAndFormats.ContainsKey(underlyingType)) { var primitiveTypeAndFormat = PrimitiveTypesAndFormats[underlyingType]; return(SerializerContract.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(SerializerContract.ForPrimitive(underlyingType, primitiveTypeAndFormat.Item1, primitiveTypeAndFormat.Item2, enumValues)); } if (underlyingType.IsDictionary(out Type keyType, out Type valueType)) { return(SerializerContract.ForDictionary(underlyingType, keyType, valueType)); } if (underlyingType.IsEnumerable(out Type itemType)) { return(SerializerContract.ForArray(underlyingType, itemType)); } return(SerializerContract.ForObject( underlyingType, GetSerializerPropertiesFor(underlyingType, out Type extensionDataValueType), extensionDataValueType)); }
private OpenApiSchema GenerateInlineSchema(SerializerContract serializerContract, SchemaRepository schemaRepository) { if (serializerContract.IsPrimitive) { return(GeneratePrimitiveSchema(serializerContract)); } if (serializerContract.IsDictionary) { return(GenerateDictionarySchema(serializerContract, schemaRepository)); } if (serializerContract.IsArray) { return(GenerateArraySchema(serializerContract, schemaRepository)); } if (serializerContract.IsObject) { return(GenerateObjectSchema(serializerContract, schemaRepository)); } return(new OpenApiSchema()); }
private OpenApiSchema GenerateObjectSchema(SerializerContract serializerContract, SchemaRepository schemaRepository) { if (serializerContract.Members == 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(serializerContract.Type).Any()) { var discriminatorName = _generatorOptions.DiscriminatorSelector(serializerContract.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 serializerMember in serializerContract.Members) { var customAttributes = serializerMember.MemberInfo?.GetInlineOrMetadataTypeAttributes() ?? Enumerable.Empty <object>(); if (_generatorOptions.IgnoreObsoleteProperties && customAttributes.OfType <ObsoleteAttribute>().Any()) { continue; } var propertySchema = GenerateSchema(serializerMember.MemberType, schemaRepository, memberInfo: serializerMember.MemberInfo); schema.Properties.Add(serializerMember.Name, propertySchema); if (serializerMember.IsRequired || customAttributes.OfType <RequiredAttribute>().Any()) { schema.Required.Add(serializerMember.Name); } if (propertySchema.Reference == null) { propertySchema.Nullable = serializerMember.IsNullable && propertySchema.Nullable; propertySchema.ReadOnly = serializerMember.IsReadOnly; propertySchema.WriteOnly = serializerMember.IsWriteOnly; } } if (serializerContract.ExtensionDataValueType != null) { schema.AdditionalProperties = GenerateSchema(serializerContract.ExtensionDataValueType, schemaRepository); } // If it's a known subType, reference the baseType for inheritied properties if (_generatorOptions.GeneratePolymorphicSchemas && (serializerContract.Type.BaseType != null) && _generatorOptions.SubTypesResolver(serializerContract.Type.BaseType).Contains(serializerContract.Type)) { var baseSerializerContract = _serializerContractResolver.GetSerializerContractForType(serializerContract.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); }