private bool TryGetDiscriminatorFor( DataContract dataContract, SchemaRepository schemaRepository, IEnumerable <DataContract> knownTypesDataContracts, out OpenApiDiscriminator discriminator) { discriminator = null; var discriminatorName = _generatorOptions.DiscriminatorNameSelector(dataContract.UnderlyingType) ?? dataContract.ObjectTypeNameProperty; if (discriminatorName == null) { return(false); } discriminator = new OpenApiDiscriminator { PropertyName = discriminatorName }; foreach (var knownTypeDataContract in knownTypesDataContracts) { var discriminatorValue = _generatorOptions.DiscriminatorValueSelector(knownTypeDataContract.UnderlyingType) ?? knownTypeDataContract.ObjectTypeNameValue; if (discriminatorValue == null) { continue; } discriminator.Mapping.Add(discriminatorValue, GenerateConcreteSchema(knownTypeDataContract, schemaRepository).Reference.ReferenceV3); } return(true); }
private OpenApiSchema CreateDictionarySchema(DataContract dataContract, SchemaRepository schemaRepository) { if (dataContract.DictionaryKeys != null) { // This is a special case where the set of key values is known (e.g. if the key type is an enum) return(new OpenApiSchema { Type = "object", Properties = dataContract.DictionaryKeys.ToDictionary( name => name, name => GenerateSchema(dataContract.DictionaryValueType, schemaRepository)), AdditionalPropertiesAllowed = false, }); } else { return(new OpenApiSchema { Type = "object", AdditionalPropertiesAllowed = true, AdditionalProperties = GenerateSchema(dataContract.DictionaryValueType, schemaRepository) }); } }
private OpenApiSchema CreateObjectSchema(DataContract dataContract, SchemaRepository schemaRepository) { var schema = new OpenApiSchema { Type = "object", Properties = new Dictionary <string, OpenApiSchema>(), Required = new SortedSet <string>(), AdditionalPropertiesAllowed = false }; var applicableDataProperties = dataContract.ObjectProperties; if (_generatorOptions.UseAllOfForInheritance || _generatorOptions.UseOneOfForPolymorphism) { if (IsKnownSubType(dataContract, out var baseTypeDataContract)) { var baseTypeSchema = GenerateConcreteSchema(baseTypeDataContract, schemaRepository); schema.AllOf.Add(baseTypeSchema); applicableDataProperties = applicableDataProperties .Where(dataProperty => dataProperty.MemberInfo.DeclaringType == dataContract.UnderlyingType); } if (IsBaseTypeWithKnownTypesDefined(dataContract, out var knownTypesDataContracts)) { foreach (var knownTypeDataContract in knownTypesDataContracts) { // Ensure schema is generated for all known types GenerateConcreteSchema(knownTypeDataContract, schemaRepository); } if (TryGetDiscriminatorFor(dataContract, schemaRepository, knownTypesDataContracts, out var discriminator)) { schema.Properties.Add(discriminator.PropertyName, new OpenApiSchema { Type = "string" }); schema.Required.Add(discriminator.PropertyName); schema.Discriminator = discriminator; } } } foreach (var dataProperty in applicableDataProperties) { var customAttributes = dataProperty.MemberInfo?.GetInlineAndMetadataAttributes() ?? Enumerable.Empty <object>(); if (_generatorOptions.IgnoreObsoleteProperties && customAttributes.OfType <ObsoleteAttribute>().Any()) { continue; } schema.Properties[dataProperty.Name] = (dataProperty.MemberInfo != null) ? GenerateSchemaForMember(dataProperty.MemberType, schemaRepository, dataProperty.MemberInfo, dataProperty) : GenerateSchemaForType(dataProperty.MemberType, schemaRepository); if ((dataProperty.IsRequired || customAttributes.OfType <RequiredAttribute>().Any()) && !schema.Required.Contains(dataProperty.Name)) { schema.Required.Add(dataProperty.Name); } } if (dataContract.ObjectExtensionDataType != null) { schema.AdditionalPropertiesAllowed = true; schema.AdditionalProperties = GenerateSchema(dataContract.ObjectExtensionDataType, schemaRepository); } return(schema); }
private OpenApiSchema GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository) { if (TryGetCustomTypeMapping(dataContract.UnderlyingType, out Func <OpenApiSchema> customSchemaFactory)) { return(customSchemaFactory()); } if (dataContract.UnderlyingType.IsAssignableToOneOf(typeof(IFormFile), typeof(FileResult))) { return(new OpenApiSchema { Type = "string", Format = "binary" }); } Func <OpenApiSchema> schemaFactory; bool returnAsReference; switch (dataContract.DataType) { case DataType.Boolean: case DataType.Integer: case DataType.Number: case DataType.String: { schemaFactory = () => CreatePrimitiveSchema(dataContract); returnAsReference = dataContract.UnderlyingType.IsEnum && !_generatorOptions.UseInlineDefinitionsForEnums; break; } case DataType.Array: { schemaFactory = () => CreateArraySchema(dataContract, schemaRepository); returnAsReference = dataContract.UnderlyingType == dataContract.ArrayItemType; break; } case DataType.Dictionary: { schemaFactory = () => CreateDictionarySchema(dataContract, schemaRepository); returnAsReference = dataContract.UnderlyingType == dataContract.DictionaryValueType; break; } case DataType.Object: { schemaFactory = () => CreateObjectSchema(dataContract, schemaRepository); returnAsReference = true; break; } default: { schemaFactory = () => new OpenApiSchema(); returnAsReference = false; break; } } return(returnAsReference ? GenerateReferencedSchema(dataContract, schemaRepository, schemaFactory) : schemaFactory()); }
private IList <OpenApiParameter> GenerateParameters(ServiceEntry apiDescription, SchemaRepository schemaRespository) { var applicableApiParameters = apiDescription.Parameters .Where(apiParam => { return(apiParam != null && UtilityType.ConvertibleType.GetTypeInfo().IsAssignableFrom(apiParam?.ParameterType)); }); return(applicableApiParameters .Select(apiParam => GenerateParameter(apiParam, schemaRespository)) .Union(new OpenApiParameter[] { CreateServiceKeyParameter(schemaRespository) }).ToList()); }
private IList <OpenApiParameter> GenerateParameters(ApiDescription apiDescription, SchemaRepository schemaRespository) { var applicableApiParameters = apiDescription.ParameterDescriptions .Where(apiParam => { return((!apiParam.IsFromBody() && !apiParam.IsFromForm()) && (!apiParam.CustomAttributes().OfType <BindNeverAttribute>().Any()) && (apiParam.ModelMetadata == null || apiParam.ModelMetadata.IsBindingAllowed)); }); return(applicableApiParameters .Select(apiParam => GenerateParameter(apiParam, schemaRespository)) .ToList()); }
private OpenApiPaths GeneratePaths(IEnumerable <ServiceEntry> apiDescriptions, SchemaRepository schemaRepository) { var apiDescriptionsByPath = apiDescriptions.OrderBy(p => p.RoutePath) .GroupBy(apiDesc => apiDesc.Descriptor.Id); var paths = new OpenApiPaths(); foreach (var group in apiDescriptionsByPath) { var key = $"/{group.Min(p => p.RoutePath).TrimStart('/')}".Trim(); if (!paths.ContainsKey(key)) { paths.Add(key, new OpenApiPathItem { Operations = GenerateOperations(group, schemaRepository) }); } else { paths.Add($"/{group.Min(p => $" {p.RoutePath}( {string.Join("_", p.Parameters.Select(m => m.ParameterType.Name))})")}", new OpenApiPathItem { Operations = GenerateOperations(group, schemaRepository) }); } } ; return(paths); }
private OpenApiPaths GeneratePaths(IEnumerable <ApiDescription> apiDescriptions, SchemaRepository schemaRepository) { var apiDescriptionsByPath = apiDescriptions .OrderBy(_options.SortKeySelector) .GroupBy(apiDesc => apiDesc.RelativePathSansParameterConstraints()); var paths = new OpenApiPaths(); foreach (var group in apiDescriptionsByPath) { paths.Add($"/{group.Key}", new OpenApiPathItem { Operations = GenerateOperations(group, schemaRepository) }); } ; return(paths); }