public override OpenApiObject GetCustomOpenApiConfig(LinkGenerator linkGenerator) { var baseConfig = base.GetCustomOpenApiConfig(linkGenerator); var types = new OpenApiArray(); if (CanSelectExisting) { types.Add(new OpenApiObject { { "type", new OpenApiString("autocomplete") }, { "label", new OpenApiString("Existing") }, { "validation", new OpenApiArray { new OpenApiString("required-from-list") } } }); // types.Add(new OpenApiObject // { // {"type", new OpenApiString("select")}, {"label", new OpenApiString("Existing S")}, // {"validation", new OpenApiArray {new OpenApiString("required-from-list")}} // }); } if (CanAddNewOrEdit) { types.Add(new OpenApiObject { { "type", new OpenApiString("subGroup") }, { "label", new OpenApiString("+ Add new / Edit") }, { "keepFieldGroup", new OpenApiBoolean(true) } }); } baseConfig["fieldTypes"] = types; return(baseConfig); }
private void CreateArrayOrListObject(string name, object value, Type type, Type nestedType, OpenApiObject openApiObject) { if (value == null) { openApiObject.Add(name, new OpenApiNull()); return; } var arrayObject = new OpenApiArray(); foreach (var item in value as IEnumerable) { if (nestedType.IsSimpleType()) { var node = CreateOpenApiObject(nestedType, item); arrayObject.Add(node); } else { var arrayItemObject = new OpenApiObject(); var properties = nestedType.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var property in properties) { var nodeValue = property.GetValue(item); ConvertRec(GetName(property.Name), nodeValue, property.PropertyType, arrayItemObject); } arrayObject.Add(arrayItemObject); } } openApiObject.Add(GetName(name), arrayObject); }
private static IOpenApiAny GetTypeNameForExample(IEdmTypeReference edmTypeReference) { switch (edmTypeReference.TypeKind()) { case EdmTypeKind.Primitive: if (edmTypeReference.IsBoolean()) { return(new OpenApiBoolean(true)); } else { return(new OpenApiString(edmTypeReference.AsPrimitive().PrimitiveDefinition().Name)); } case EdmTypeKind.Entity: case EdmTypeKind.Complex: case EdmTypeKind.Enum: OpenApiObject obj = new OpenApiObject(); obj["@odata.type"] = new OpenApiString(edmTypeReference.FullName()); return(obj); case EdmTypeKind.Collection: OpenApiArray array = new OpenApiArray(); IEdmTypeReference elementType = edmTypeReference.AsCollection().ElementType(); array.Add(GetTypeNameForExample(elementType)); return(array); case EdmTypeKind.Untyped: case EdmTypeKind.TypeDefinition: case EdmTypeKind.EntityReference: default: throw new OpenApiException("Not support for the type kind " + edmTypeReference.TypeKind()); } }
public void Apply(OpenApiSchema schema, SchemaFilterContext context) { var type = context.Type; if (type.IsEnum) { var values = Enum.GetValues(type); var valueArr = new OpenApiArray(); foreach (var value in values) { var item = new OpenApiObject { ["name"] = new OpenApiString(Enum.GetName(type, value)), ["value"] = new OpenApiString(value.ToString()) }; valueArr.Add(item); } schema.Extensions.Add( "x-ms-enum", new OpenApiObject { ["name"] = new OpenApiString(type.Name), ["modelAsString"] = new OpenApiBoolean(true), ["values"] = valueArr } ); } }
private bool TryParse(JsonElement token, out IOpenApiAny?any) { any = null; switch (token.ValueKind) { case JsonValueKind.Array: var array = new OpenApiArray(); foreach (var value in token.EnumerateArray()) { if (TryParse(value, out var child)) { array.Add(child); } } any = array; return(true); case JsonValueKind.False: any = new OpenApiBoolean(false); return(true); case JsonValueKind.True: any = new OpenApiBoolean(true); return(true); case JsonValueKind.Number: any = new OpenApiDouble(token.GetDouble()); return(true); case JsonValueKind.String: any = new OpenApiString(token.GetString()); return(true); case JsonValueKind.Object: var obj = new OpenApiObject(); foreach (var child in token.EnumerateObject()) { if (TryParse(child.Value, out var value)) { obj[child.Name] = value; } } any = obj; return(true); case JsonValueKind.Null: case JsonValueKind.Undefined: default: return(false); } }
public override IOpenApiAny ParseIntoAny() { var array = new OpenApiArray(); foreach (var node in childNodes) { array.Add(node.ParseIntoAny()); } return(array); }
/// <summary> /// Create a <see cref="OpenApiArray"/> /// </summary> /// <returns>The created Any object.</returns> public override IOpenApiAny CreateAny() { var array = new OpenApiArray(); foreach (var node in this) { array.Add(node.CreateAny()); } return(array); }
private static IOpenApiAny CreateOpenApiArray(JsonElement jsonElement) { var openApiArray = new OpenApiArray(); foreach (var item in jsonElement.EnumerateArray()) { openApiArray.Add(CreateFromJsonElement(item)); } return(openApiArray); }
static public IOpenApiAny GetExample(Type parameter, TypeMaps maps, OpenApiComponents components) { if (components.Schemas.ContainsKey(parameter.Name)) { return(components.Schemas[parameter.Name].Example); } if (maps.ContainsMap(parameter)) { return(maps.GetMap(parameter).OpenApiExample); } else if (parameter == typeof(string)) { int randomNum = new Random().Next() % 3; var words = new string[] { "foo", "bar", "baz" }; return(new OpenApiString(words[randomNum])); } else if (IsNumericType(parameter)) { int randomNum = new Random().Next() % 400; return(new OpenApiInteger(randomNum)); } else if (parameter == typeof(bool)) { int randomNum = new Random().Next() % 1; return(new OpenApiBoolean(randomNum == 0)); } else if (parameter.GetInterfaces().Contains(typeof(IEnumerable))) { var exampleArr = new OpenApiArray(); int randomNum = new Random().Next() % 3; for (int _ = 0; _ < randomNum + 1; _++) { var innerType = parameter.GetElementType() ?? parameter.GenericTypeArguments[0]; exampleArr.Add(GetExample(innerType, maps, components)); } return(exampleArr); } else { if (parameter.GetProperties().Length == 0) { return(new OpenApiNull()); } var example = new OpenApiObject(); foreach (var prop in parameter.GetProperties()) { example.Add(prop.Name, GetExample(prop.PropertyType, maps, components)); } return(example); } }
/// <inheritdoc/> protected override void SetExtensions(OpenApiPathItem item) { if (!Context.Settings.ShowMsDosGroupPath) { return; } IList <ODataPath> samePaths = new List <ODataPath>(); foreach (var path in Context.AllPaths.Where(p => p.Kind == ODataPathKind.NavigationProperty && p != Path)) { bool lastIsKeySegment = path.LastSegment is ODataKeySegment; if (LastSegmentIsKeySegment != lastIsKeySegment) { continue; } ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment; if (NavigationSource != navigationSourceSegment.NavigationSource) { continue; } ODataNavigationPropertySegment npSegment = path.LastSegment as ODataNavigationPropertySegment; if (npSegment == null) { npSegment = path.Segments[path.Count - 2] as ODataNavigationPropertySegment; } if (NavigationProperty != npSegment.NavigationProperty) { continue; } samePaths.Add(path); } if (samePaths.Any()) { OpenApiArray array = new OpenApiArray(); OpenApiConvertSettings settings = Context.Settings.Clone(); settings.EnableKeyAsSegment = Context.KeyAsSegment; foreach (var p in samePaths) { array.Add(new OpenApiString(p.GetPathItemName(settings))); } item.Extensions.Add(Constants.xMsDosGroupPath, array); } }
private static IOpenApiAny CreateOpenApiArray(JsonElement jsonElement) { var openApiArray = new OpenApiArray(); foreach (var item in jsonElement.EnumerateArray()) { var json = item.ValueKind == JsonValueKind.String ? $"\"{item}\"" : item.ToString(); openApiArray.Add(CreateFromJson(json)); } return(openApiArray); }
private static IOpenApiAny CreateOpenApiArray(IEnumerable <JsonElement> jsonElements) { var openApiArray = new OpenApiArray(); foreach (var jsonElement in jsonElements) { var json = jsonElement.ValueKind == JsonValueKind.String ? $"\"{jsonElement}\"" : jsonElement.ToString(); openApiArray.Add(CreateFromJson(json)); } return(openApiArray); }
/// <inheritdoc/> protected override void SetExtensions(OpenApiPathItem item) { if (!Context.Settings.ShowMsDosGroupPath) { return; } ODataNavigationSourceSegment navigationSourceSegment = Path.FirstSegment as ODataNavigationSourceSegment; IEdmNavigationSource currentNavSource = navigationSourceSegment.NavigationSource; IList <ODataPath> samePaths = new List <ODataPath>(); foreach (var path in Context.AllPaths.Where(p => p.Kind == ODataPathKind.Operation && p != Path)) { navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment; if (currentNavSource != navigationSourceSegment.NavigationSource) { continue; } ODataOperationSegment operationSegment = path.LastSegment as ODataOperationSegment; if (EdmOperation.FullName() != operationSegment.Operation.FullName()) { continue; } samePaths.Add(path); } if (samePaths.Any()) { OpenApiArray array = new OpenApiArray(); OpenApiConvertSettings settings = Context.Settings.Clone(); settings.EnableKeyAsSegment = Context.KeyAsSegment; foreach (var p in samePaths) { array.Add(new OpenApiString(p.GetPathItemName(settings))); } item.Extensions.Add(Constants.xMsDosGroupPath, array); } base.SetExtensions(item); item.Extensions.AddCustomAtributesToExtensions(Context, EdmOperation); }
private void Transform(string key, OpenApiSchema schema, OpenApiObject openApiObject) { var type = schema.Type; var format = schema.Format; if (type == "object") { var item = new OpenApiObject(); foreach (var(itemKey, itemProperty) in schema.Properties) { Transform(itemKey, itemProperty, item); } openApiObject.Add(key, item); } else if (type == "array") { if (schema.Items.Type == "object") { var item = new OpenApiObject(); foreach (var(itemKey, itemProperty) in schema.Items.Properties) { Transform(itemKey, itemProperty, item); } var items = new OpenApiArray { item }; openApiObject.Add(key, items); } else { var items = new OpenApiArray(); var item = GetOpenApiValue(schema.Items); items.Add(item); openApiObject.Add(key, items); } } else { var openApiValue = GetOpenApiValue(schema); openApiObject.Add(key, openApiValue); } }
private static IOpenApiAny GetTypeNameForExample(ODataContext context, IEdmTypeReference edmTypeReference) { switch (edmTypeReference.TypeKind()) { case EdmTypeKind.Primitive: IEdmPrimitiveType primitiveType = edmTypeReference.AsPrimitive().PrimitiveDefinition(); OpenApiSchema schema = context.CreateSchema(primitiveType); if (edmTypeReference.IsBoolean()) { return(new OpenApiBoolean(true)); } else { if (schema.Reference != null) { return(new OpenApiString(schema.Reference.Id)); } else { return(new OpenApiString(schema.Type ?? schema.Format)); } } case EdmTypeKind.Entity: case EdmTypeKind.Complex: case EdmTypeKind.Enum: OpenApiObject obj = new OpenApiObject(); obj[Constants.OdataType] = new OpenApiString(edmTypeReference.FullName()); return(obj); case EdmTypeKind.Collection: OpenApiArray array = new OpenApiArray(); IEdmTypeReference elementType = edmTypeReference.AsCollection().ElementType(); array.Add(GetTypeNameForExample(context, elementType)); return(array); case EdmTypeKind.Untyped: case EdmTypeKind.TypeDefinition: case EdmTypeKind.EntityReference: default: throw new OpenApiException("Not support for the type kind " + edmTypeReference.TypeKind()); } }
public void Apply(OpenApiOperation operation, OperationFilterContext context) { var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true) .Union(context.MethodInfo.GetCustomAttributes(true)) .OfType <RapiDocLabelAttribute>(); if (authAttributes.Any()) { var openapiArray = new OpenApiArray(); foreach (var item in authAttributes) { openapiArray.Add(new OpenApiObject { ["color"] = new OpenApiString(item.Color.ToString().ToLower().Replace("_", "-")), ["label"] = new OpenApiString(item.Label) }); } operation.Extensions.Add("x-badges", openapiArray); } ; }
private static void SetEnumExtensionValues(OpenApiSchema schema, Type type) { var enumValues = Enum.GetValues(type); var enumExtensionValues = new OpenApiArray(); foreach (var enumValue in enumValues) { var item = new OpenApiObject { ["name"] = new OpenApiString(Enum.GetName(type, enumValue)), ["value"] = new OpenApiString(enumValue.GetHashCode().ToString()) }; enumExtensionValues.Add(item); } schema.Extensions.Add("x_ms_enum", new OpenApiObject { ["values"] = enumExtensionValues } ); }
private static IOpenApiAny GetTypeNameForExample(IEdmTypeReference edmTypeReference) { switch (edmTypeReference.TypeKind()) { case EdmTypeKind.Primitive: if (edmTypeReference.IsBinary()) { // return new OpenApiBinary(new byte[] { 0x00 }); issue on binary writing return(new OpenApiString(Convert.ToBase64String(new byte[] { 0x00 }))); } else if (edmTypeReference.IsBoolean()) { return(new OpenApiBoolean(true)); } else if (edmTypeReference.IsByte()) { return(new OpenApiByte(0x00)); } else if (edmTypeReference.IsDate()) { return(new OpenApiDate(DateTime.MinValue)); } else if (edmTypeReference.IsDateTimeOffset()) { return(new OpenApiDateTime(DateTimeOffset.MinValue)); } else if (edmTypeReference.IsDecimal() || edmTypeReference.IsDouble()) { return(new OpenApiDouble(0D)); } else if (edmTypeReference.IsFloating()) { return(new OpenApiFloat(0F)); } else if (edmTypeReference.IsGuid()) { return(new OpenApiString(Guid.Empty.ToString())); } else if (edmTypeReference.IsInt16() || edmTypeReference.IsInt32()) { return(new OpenApiInteger(0)); } else if (edmTypeReference.IsInt64()) { return(new OpenApiLong(0L)); } else { return(new OpenApiString(edmTypeReference.AsPrimitive().PrimitiveDefinition().Name)); } case EdmTypeKind.Entity: case EdmTypeKind.Complex: case EdmTypeKind.Enum: OpenApiObject obj = new OpenApiObject(); obj["@odata.type"] = new OpenApiString(edmTypeReference.FullName()); return(obj); case EdmTypeKind.Collection: OpenApiArray array = new OpenApiArray(); IEdmTypeReference elementType = edmTypeReference.AsCollection().ElementType(); array.Add(GetTypeNameForExample(elementType)); return(array); case EdmTypeKind.TypeDefinition: var typedef = edmTypeReference.AsTypeDefinition().TypeDefinition(); return(GetTypeNameForExample(new EdmPrimitiveTypeReference(typedef.UnderlyingType, edmTypeReference.IsNullable))); case EdmTypeKind.Untyped: case EdmTypeKind.EntityReference: default: throw new OpenApiException("Not support for the type kind " + edmTypeReference.TypeKind()); } }
/// <summary> /// Converts the <see cref="OpenApiString"/>s in the given <see cref="IOpenApiAny"/> /// into the appropriate <see cref="IOpenApiPrimitive"/> type based on the given <see cref="OpenApiSchema"/>. /// For those strings that the schema does not specify the type for, convert them into /// the most specific type based on the value. /// </summary> public static IOpenApiAny GetSpecificOpenApiAny(IOpenApiAny openApiAny, OpenApiSchema schema) { if (openApiAny is OpenApiArray openApiArray) { var newArray = new OpenApiArray(); foreach (var element in openApiArray) { newArray.Add(GetSpecificOpenApiAny(element, schema?.Items)); } return(newArray); } if (openApiAny is OpenApiObject openApiObject) { var newObject = new OpenApiObject(); foreach (var key in openApiObject.Keys.ToList()) { if (schema != null && schema.Properties != null && schema.Properties.ContainsKey(key)) { newObject[key] = GetSpecificOpenApiAny(openApiObject[key], schema.Properties[key]); } else { newObject[key] = GetSpecificOpenApiAny(openApiObject[key], schema?.AdditionalProperties); } } return(newObject); } if (!(openApiAny is OpenApiString)) { return(openApiAny); } if (schema?.Type == null) { return(GetSpecificOpenApiAny(openApiAny)); } var type = schema.Type; var format = schema.Format; var value = ((OpenApiString)openApiAny).Value; if (value == null || value == "null") { return(new OpenApiNull()); } if (type == "integer" && format == "int32") { if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue)) { return(new OpenApiInteger(intValue)); } } if (type == "integer" && format == "int64") { if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue)) { return(new OpenApiLong(longValue)); } } if (type == "integer") { if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue)) { return(new OpenApiInteger(intValue)); } } if (type == "number" && format == "float") { if (float.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var floatValue)) { return(new OpenApiFloat(floatValue)); } } if (type == "number" && format == "double") { if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue)) { return(new OpenApiDouble(doubleValue)); } } if (type == "number") { if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue)) { return(new OpenApiDouble(doubleValue)); } } if (type == "string" && format == "byte") { if (byte.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var byteValue)) { return(new OpenApiByte(byteValue)); } } // TODO: Parse byte array to OpenApiBinary type. if (type == "string" && format == "date") { if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateValue)) { return(new OpenApiDate(dateValue.Date)); } } if (type == "string" && format == "date-time") { if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue)) { return(new OpenApiDateTime(dateTimeValue)); } } if (type == "string" && format == "password") { return(new OpenApiPassword(value)); } if (type == "string") { return(new OpenApiString(value)); } if (type == "boolean") { if (bool.TryParse(value, out var booleanValue)) { return(new OpenApiBoolean(booleanValue)); } } // If data conflicts with the given type, return a string. // This converter is used in the parser, so it does not perform any validations, // but the validator can be used to validate whether the data and given type conflicts. return(new OpenApiString(value)); }
/// <summary> /// Converts the <see cref="OpenApiString"/>s in the given <see cref="IOpenApiAny"/> /// into the most specific <see cref="IOpenApiPrimitive"/> type based on the value. /// </summary> public static IOpenApiAny GetSpecificOpenApiAny(IOpenApiAny openApiAny) { if (openApiAny is OpenApiArray openApiArray) { var newArray = new OpenApiArray(); foreach (var element in openApiArray) { newArray.Add(GetSpecificOpenApiAny(element)); } return(newArray); } if (openApiAny is OpenApiObject openApiObject) { var newObject = new OpenApiObject(); foreach (var key in openApiObject.Keys.ToList()) { newObject[key] = GetSpecificOpenApiAny(openApiObject[key]); } return(newObject); } if (!(openApiAny is OpenApiString)) { return(openApiAny); } var value = ((OpenApiString)openApiAny).Value; if (value == null || value == "null") { return(new OpenApiNull()); } if (value == "true") { return(new OpenApiBoolean(true)); } if (value == "false") { return(new OpenApiBoolean(false)); } if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue)) { return(new OpenApiInteger(intValue)); } if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue)) { return(new OpenApiLong(longValue)); } if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue)) { return(new OpenApiDouble(doubleValue)); } if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue)) { return(new OpenApiDateTime(dateTimeValue)); } // if we can't identify the type of value, return it as string. return(new OpenApiString(value)); }
/// <summary> /// Converts the <see cref="OpenApiString"/>s in the given <see cref="IOpenApiAny"/> /// into the appropriate <see cref="IOpenApiPrimitive"/> type based on the given <see cref="OpenApiSchema"/>. /// For those strings that the schema does not specify the type for, convert them into /// the most specific type based on the value. /// </summary> public static IOpenApiAny GetSpecificOpenApiAny(IOpenApiAny openApiAny, OpenApiSchema schema = null) { if (openApiAny is OpenApiArray openApiArray) { var newArray = new OpenApiArray(); foreach (var element in openApiArray) { newArray.Add(GetSpecificOpenApiAny(element, schema?.Items)); } return(newArray); } if (openApiAny is OpenApiObject openApiObject) { var newObject = new OpenApiObject(); foreach (var key in openApiObject.Keys.ToList()) { if (schema?.Properties != null && schema.Properties.TryGetValue(key, out var property)) { newObject[key] = GetSpecificOpenApiAny(openApiObject[key], property); } else { newObject[key] = GetSpecificOpenApiAny(openApiObject[key], schema?.AdditionalProperties); } } return(newObject); } if (!(openApiAny is OpenApiString)) { return(openApiAny); } var value = ((OpenApiString)openApiAny).Value; var type = schema?.Type; var format = schema?.Format; if (((OpenApiString)openApiAny).IsExplicit()) { // More narrow type detection for explicit strings, only check types that are passed as strings if (schema == null) { if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue)) { return(new OpenApiDateTime(dateTimeValue)); } } else if (type == "string") { if (format == "byte") { try { return(new OpenApiByte(Convert.FromBase64String(value))); } catch (FormatException) { } } if (format == "binary") { try { return(new OpenApiBinary(Encoding.UTF8.GetBytes(value))); } catch (EncoderFallbackException) { } } if (format == "date") { if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateValue)) { return(new OpenApiDate(dateValue.Date)); } } if (format == "date-time") { if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue)) { return(new OpenApiDateTime(dateTimeValue)); } } if (format == "password") { return(new OpenApiPassword(value)); } } return(openApiAny); } if (value == null || value == "null") { return(new OpenApiNull()); } if (schema?.Type == null) { if (value == "true") { return(new OpenApiBoolean(true)); } if (value == "false") { return(new OpenApiBoolean(false)); } if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue)) { return(new OpenApiInteger(intValue)); } if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue)) { return(new OpenApiLong(longValue)); } if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue)) { return(new OpenApiDouble(doubleValue)); } if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue)) { return(new OpenApiDateTime(dateTimeValue)); } } else { if (type == "integer" && format == "int32") { if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue)) { return(new OpenApiInteger(intValue)); } } if (type == "integer" && format == "int64") { if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue)) { return(new OpenApiLong(longValue)); } } if (type == "integer") { if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue)) { return(new OpenApiInteger(intValue)); } } if (type == "number" && format == "float") { if (float.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var floatValue)) { return(new OpenApiFloat(floatValue)); } } if (type == "number" && format == "double") { if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue)) { return(new OpenApiDouble(doubleValue)); } } if (type == "number") { if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue)) { return(new OpenApiDouble(doubleValue)); } } if (type == "string" && format == "byte") { try { return(new OpenApiByte(Convert.FromBase64String(value))); } catch (FormatException) { } } // binary if (type == "string" && format == "binary") { try { return(new OpenApiBinary(Encoding.UTF8.GetBytes(value))); } catch (EncoderFallbackException) { } } if (type == "string" && format == "date") { if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateValue)) { return(new OpenApiDate(dateValue.Date)); } } if (type == "string" && format == "date-time") { if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue)) { return(new OpenApiDateTime(dateTimeValue)); } } if (type == "string" && format == "password") { return(new OpenApiPassword(value)); } if (type == "string") { return(openApiAny); } if (type == "boolean") { if (bool.TryParse(value, out var booleanValue)) { return(new OpenApiBoolean(booleanValue)); } } } // If data conflicts with the given type, return a string. // This converter is used in the parser, so it does not perform any validations, // but the validator can be used to validate whether the data and given type conflicts. return(openApiAny); }
public static IOpenApiAny Resolve(IOpenApiAny any, OpenApiSchema schema = null) { if (any is OpenApiArray arrayAny) { var newArray = new OpenApiArray(); foreach (var element in arrayAny) { newArray.Add(Resolve(element, schema?.Items)); } return(newArray); } if (any is OpenApiObject objectAny) { var newObject = new OpenApiObject(); foreach (var propertyName in objectAny.Keys.ToList()) { if (schema?.Properties != null && schema.Properties.ContainsKey(propertyName)) { newObject[propertyName] = Resolve(objectAny[propertyName], schema.Properties[propertyName]); } else if (schema?.AdditionalProperties != null && schema.AdditionalProperties is OpenApiSchema ss) { newObject[propertyName] = Resolve(objectAny[propertyName], ss); } } return(newObject); } if (!(any is OpenApiString)) { return(any); // already a non-string OpenApiAny } var value = ((OpenApiString)any).Value; if (((OpenApiString)any).Quoted) // quoted string { if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue)) { return(new OpenApiDateTime(dateTimeValue)); } return(any); // actual type is OpenApiString } if (value == null) { return(new OpenApiNull()); } if (schema?.Type == null) { if (value == "true") { return(new OpenApiBoolean(true)); } if (value == "false") { return(new OpenApiBoolean(false)); } if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue)) { return(new OpenApiInt32(intValue)); } if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue)) { return(new OpenApiInt64(longValue)); } if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue)) { return(new OpenApiDouble(doubleValue)); } if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue)) { return(new OpenApiDateTime(dateTimeValue)); } } else { if (schema.Type == "integer") { if (schema.Format != null && schema.Format == "int64") { if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue)) { return(new OpenApiInt64(longValue)); } } else { if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue)) { return(new OpenApiInt32(intValue)); } } } if (schema.Type == "number") { if (schema.Format != null && schema.Format == "float") { if (float.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var floatValue)) { return(new OpenApiFloat(floatValue)); } } else { if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue)) { return(new OpenApiDouble(doubleValue)); } } } if (schema.Type == "string") { if (schema.Format != null && schema.Format == "byte") { try { return(new OpenApiByte(Convert.FromBase64String(value))); } catch (FormatException) { } } else if (schema.Format != null && schema.Format == "binary") { try { return(new OpenApiBinary(Encoding.UTF8.GetBytes(value))); } catch (EncoderFallbackException) { } } else if (schema.Format != null && (schema.Format == "date" || schema.Format == "date-time")) { if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateValue)) { return(new OpenApiDate(dateValue.Date)); } } else if (schema.Format != null && schema.Format == "password") { return(new OpenApiPassword(value)); } else { return(new OpenApiString(value)); } } if (schema.Type == "boolean") { if (bool.TryParse(value, out var booleanValue)) { return(new OpenApiBoolean(booleanValue)); } } } return(any); }
/// <summary> /// Finds the existing reference object based on the key from the input or creates a new one. /// </summary> /// <returns>The existing or created reference object.</returns> internal override OpenApiSchema FindOrAddReference(Type input) { // Return empty schema when the type does not have a name. // This can occur, for example, when a generic type without the generic argument specified // is passed in. if (input == null || input.FullName == null) { return(new OpenApiSchema()); } var key = GetKey(input); // If the schema already exists in the References, simply return. if (References.ContainsKey(key)) { return(new OpenApiSchema { Reference = new OpenApiReference { Id = key, Type = ReferenceType.Schema } }); } try { // There are multiple cases for input types that should be handled differently to match the OpenAPI spec. // // 1. Simple Type // 2. Enum Type // 3. Dictionary Type // 4. Enumerable Type // 5. Object Type var schema = new OpenApiSchema(); if (input.IsSimple()) { schema = input.MapToOpenApiSchema(); // Certain simple types yield more specific information. if (input == typeof(char)) { schema.MinLength = 1; schema.MaxLength = 1; } else if (input == typeof(Guid)) { schema.Example = new OpenApiString(Guid.Empty.ToString()); } return(schema); } if (input == typeof(Stream) || input.BaseType == typeof(Stream)) { schema.Type = "string"; schema.Format = "binary"; return(schema); } if (input.IsEnum) { var enumValues = Enum.GetValues(input); var xEnumVarNames = new OpenApiArray(); foreach (var enumValue in enumValues) { var enumName = Enum.GetName(input, enumValue); if (schema.Type == null) { if (Enum.GetUnderlyingType(input).ToString() == "System.Int32") { schema.Type = "integer"; schema.Format = "int32"; } else { schema.Type = "string"; } } if (schema.Type == "integer") { schema.Enum.Add(new OpenApiInteger((int)enumValue)); xEnumVarNames.Add(new OpenApiString(enumName)); } else { schema.Enum.Add(new OpenApiString(enumName)); } } if (xEnumVarNames.Count > 0) { schema.Extensions.Add("x-enum-varnames", xEnumVarNames); } return(schema); } if (input.IsDictionary()) { schema.Type = "object"; schema.AdditionalProperties = FindOrAddReference(input.GetGenericArguments()[1]); return(schema); } if (input.IsEnumerable()) { schema.Type = "array"; schema.Items = FindOrAddReference(input.GetEnumerableItemType()); return(schema); } var nullableUnderlyingType = Nullable.GetUnderlyingType(input); if (nullableUnderlyingType?.IsEnum == true) { schema.Type = "string"; schema.Nullable = true; foreach (var name in nullableUnderlyingType.GetEnumNames()) { schema.Enum.Add(new OpenApiString(name)); } return(schema); } schema.Type = "object"; // Note this assignment is necessary to allow self-referencing type to finish // without causing stack overflow. // We can also assume that the schema is an object type at this point. References[key] = schema; var propertyNameDeclaringTypeMap = new Dictionary <string, Type>(); var typeAttributes = input.GetCustomAttributes(false); foreach (var typeAttribute in typeAttributes) { if (typeAttribute.GetType().FullName == "Newtonsoft.Json.JsonObjectAttribute") { var type = typeAttribute.GetType(); var namingStrategyInfo = type.GetProperty("NamingStrategyType"); if (namingStrategyInfo != null) { var namingStrategyValue = namingStrategyInfo.GetValue(typeAttribute, null); if (namingStrategyValue?.ToString() == "Newtonsoft.Json.Serialization.CamelCaseNamingStrategy") { _propertyNameResolver = new CamelCasePropertyNameResolver(); } } } } var a = input.FullName; foreach (var propertyInfo in input.GetProperties()) { var ignoreProperty = false; var innerSchema = FindOrAddReference(propertyInfo.PropertyType); var propertyName = _propertyNameResolver.ResolvePropertyName(propertyInfo); // Construct property name like it shows up in documentation xml. var propertyFullName = propertyInfo.DeclaringType.Namespace + "." + propertyInfo.DeclaringType?.Name + "." + propertyInfo.Name; if (this._propertyDescriptionMap.ContainsKey(propertyFullName)) { innerSchema.Description = this._propertyDescriptionMap[propertyFullName]; } var attributes = propertyInfo.GetCustomAttributes(false); foreach (var attribute in attributes) { if (attribute.GetType().FullName == "Newtonsoft.Json.JsonPropertyAttribute") { var type = attribute.GetType(); var requiredPropertyInfo = type.GetProperty("Required"); if (requiredPropertyInfo != null) { var requiredValue = Enum.GetName( requiredPropertyInfo.PropertyType, requiredPropertyInfo.GetValue(attribute, null)); if (requiredValue == "Always") { schema.Required.Add(propertyName); } } } if (attribute.GetType().FullName == "Newtonsoft.Json.JsonIgnoreAttribute") { ignoreProperty = true; } } if (ignoreProperty) { continue; } var propertyDeclaringType = propertyInfo.DeclaringType; if (propertyNameDeclaringTypeMap.ContainsKey(propertyName)) { var existingPropertyDeclaringType = propertyNameDeclaringTypeMap[propertyName]; var duplicateProperty = true; if (existingPropertyDeclaringType != null && propertyDeclaringType != null) { if (propertyDeclaringType.IsSubclassOf(existingPropertyDeclaringType) || (existingPropertyDeclaringType.IsInterface && propertyDeclaringType.ImplementInterface(existingPropertyDeclaringType))) { // Current property is on a derived class and hides the existing schema.Properties[propertyName] = innerSchema; duplicateProperty = false; } if (existingPropertyDeclaringType.IsSubclassOf(propertyDeclaringType) || (propertyDeclaringType.IsInterface && existingPropertyDeclaringType.ImplementInterface(propertyDeclaringType))) { // current property is hidden by the existing so don't add it continue; } } if (duplicateProperty) { throw new AddingSchemaReferenceFailedException( key, string.Format( SpecificationGenerationMessages.DuplicateProperty, propertyName, input)); } } schema.Properties[propertyName] = innerSchema; propertyNameDeclaringTypeMap.Add(propertyName, propertyDeclaringType); } References[key] = schema; return(new OpenApiSchema { Reference = new OpenApiReference { Id = key, Type = ReferenceType.Schema } }); } catch (Exception e) { // Something went wrong while fetching schema, so remove the key if exists from the references. if (References.ContainsKey(key)) { References.Remove(key); } throw new AddingSchemaReferenceFailedException(key, e.Message); } }