Exemplo n.º 1
0
        private void LoadEnumerations(Type type, JsonSchema4 schema, JsonObjectTypeDescription typeDescription)
        {
            schema.Type = typeDescription.Type;
            schema.Enumeration.Clear();
            schema.EnumerationNames.Clear();

            foreach (var enumName in Enum.GetNames(type))
            {
                if (typeDescription.Type == JsonObjectType.Integer)
                {
                    var value = Convert.ChangeType(Enum.Parse(type, enumName), Enum.GetUnderlyingType(type));
                    schema.Enumeration.Add(value);
                }
                else
                {
                    var     attributes          = type.GetTypeInfo().GetDeclaredField(enumName).GetCustomAttributes(); // EnumMember only checked if StringEnumConverter is used
                    dynamic enumMemberAttribute = attributes.TryGetIfAssignableTo("System.Runtime.Serialization.EnumMemberAttribute");
                    if (enumMemberAttribute != null && !string.IsNullOrEmpty(enumMemberAttribute.Value))
                    {
                        schema.Enumeration.Add((string)enumMemberAttribute.Value);
                    }
                    else
                    {
                        schema.Enumeration.Add(enumName);
                    }
                }

                schema.EnumerationNames.Add(enumName);
            }
        }
Exemplo n.º 2
0
        private async Task AddKnownTypeAsync(Type type, JsonSchemaResolver schemaResolver)
        {
            var typeDescription = JsonObjectTypeDescription.FromType(type, ResolveContract(type), null, Settings.DefaultEnumHandling);
            var isIntegerEnum   = typeDescription.Type == JsonObjectType.Integer;

            if (!schemaResolver.HasSchema(type, isIntegerEnum))
            {
                await GenerateAsync(type, schemaResolver).ConfigureAwait(false);
            }
        }
Exemplo n.º 3
0
        private bool RequiresSchemaReference(Type type, IEnumerable <Attribute> parentAttributes)
        {
            var typeDescription = JsonObjectTypeDescription.FromType(type, parentAttributes, Settings.DefaultEnumHandling);

            var typeMapper = Settings.TypeMappers.FirstOrDefault(m => m.MappedType == type);

            if (typeMapper != null)
            {
                return(typeMapper.UseReference);
            }

            return(!typeDescription.IsDictionary && (typeDescription.Type.HasFlag(JsonObjectType.Object) || typeDescription.IsEnum));
        }
        private void GenerateKnownTypes(Type type, JsonSchemaResolver schemaResolver)
        {
            foreach (dynamic knownTypeAttribute in type.GetTypeInfo().GetCustomAttributes().Where(a => a.GetType().Name == "KnownTypeAttribute"))
            {
                var typeDescription = JsonObjectTypeDescription.FromType(knownTypeAttribute.Type, null, Settings.DefaultEnumHandling);
                var isIntegerEnum   = typeDescription.Type == JsonObjectType.Integer;

                if (!schemaResolver.HasSchema(knownTypeAttribute.Type, isIntegerEnum))
                {
                    Generate(knownTypeAttribute.Type, schemaResolver);
                }
            }
        }
Exemplo n.º 5
0
        private void GenerateKnownTypes(Type type, JsonSchema4 rootSchema, ISchemaDefinitionAppender schemaDefinitionAppender, ISchemaResolver schemaResolver)
        {
            foreach (var knownTypeAttribute in type.GetTypeInfo().GetCustomAttributes <KnownTypeAttribute>())
            {
                var typeDescription = JsonObjectTypeDescription.FromType(knownTypeAttribute.Type, null, Settings.DefaultEnumHandling);
                var isIntegerEnum   = typeDescription.Type == JsonObjectType.Integer;

                if (!schemaResolver.HasSchema(knownTypeAttribute.Type, isIntegerEnum))
                {
                    var knownSchema = Generate(knownTypeAttribute.Type, rootSchema, null, schemaDefinitionAppender, schemaResolver);
                    schemaDefinitionAppender.Append(rootSchema, knownSchema.ActualSchema);
                }
            }
        }
Exemplo n.º 6
0
 private object ConvertDefaultValue(Type parentType, IEnumerable <Attribute> propertyAttributes, dynamic defaultValueAttribute)
 {
     if (((Type)defaultValueAttribute.Value.GetType()).GetTypeInfo().IsEnum)
     {
         if (JsonObjectTypeDescription.IsStringEnum(parentType, propertyAttributes, Settings.DefaultEnumHandling))
         {
             return(defaultValueAttribute.Value.ToString());
         }
         else
         {
             return((int)defaultValueAttribute.Value);
         }
     }
     else
     {
         return(defaultValueAttribute.Value);
     }
 }
Exemplo n.º 7
0
        private string[] GetEnumNames(Type type, JsonObjectTypeDescription typeDescription)
        {
            if (typeDescription.Type == JsonObjectType.String)
            {
                return(Enum.GetNames(type).Select(name =>
                {
                    var attributes = type.GetTypeInfo().GetDeclaredField(name).GetCustomAttributes();
                    dynamic enumMemberAttribute = TryGetAttribute(attributes, "System.Runtime.Serialization.EnumMemberAttribute");
                    if (enumMemberAttribute != null && !string.IsNullOrEmpty(enumMemberAttribute.Value))
                    {
                        return (string)enumMemberAttribute.Value;
                    }
                    return name;
                }).ToArray());
            }

            return(Enum.GetNames(type));
        }
Exemplo n.º 8
0
        private void LoadEnumerations(Type type, JsonSchema4 schema, JsonObjectTypeDescription typeDescription)
        {
            schema.Type = typeDescription.Type;
            schema.Enumeration.Clear();
            schema.EnumerationNames.Clear();

            foreach (var enumName in GetEnumNames(type, typeDescription))
            {
                if (typeDescription.Type == JsonObjectType.Integer)
                {
                    var value = Convert.ChangeType(Enum.Parse(type, enumName), Enum.GetUnderlyingType(type));
                    schema.Enumeration.Add(value);
                }
                else
                {
                    schema.Enumeration.Add(enumName);
                }
                schema.EnumerationNames.Add(enumName);
            }
        }
Exemplo n.º 9
0
        /// <summary>Generates a <see cref="JsonSchema4" /> object for the given type and adds the mapping to the given resolver.</summary>
        /// <param name="type">The type.</param>
        /// <param name="parentAttributes">The parent property or parameter attributes.</param>
        /// <param name="schemaResolver"></param>
        /// <param name="schemaDefinitionAppender"></param>
        /// <returns>The schema.</returns>
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        public virtual TSchemaType Generate <TSchemaType>(Type type, IEnumerable <Attribute> parentAttributes,
                                                          ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
            where TSchemaType : JsonSchema4, new()
        {
            var schema = HandleSpecialTypes <TSchemaType>(type, schemaResolver);

            if (schema != null)
            {
                return(schema);
            }

            schema = new TSchemaType();

            if (schemaDefinitionAppender.RootObject == null)
            {
                schemaDefinitionAppender.RootObject = schema;
            }

            ApplyExtensionDataAttributes(schema, type, parentAttributes);

            var typeDescription = JsonObjectTypeDescription.FromType(type, parentAttributes, Settings.DefaultEnumHandling);

            if (typeDescription.Type.HasFlag(JsonObjectType.Object))
            {
                if (typeDescription.IsDictionary)
                {
                    typeDescription.ApplyType(schema);
                    GenerateDictionary(type, schema, schemaResolver, schemaDefinitionAppender);
                }
                else
                {
                    if (schemaResolver.HasSchema(type, false))
                    {
                        schema.SchemaReference = schemaResolver.GetSchema(type, false);
                        return(schema);
                    }

                    if (schema.GetType() == typeof(JsonSchema4))
                    {
                        typeDescription.ApplyType(schema);

                        schema.TypeNameRaw = ReflectionExtensions.GetSafeTypeName(type);
                        schema.Description = GetDescription(type.GetTypeInfo(), type.GetTypeInfo().GetCustomAttributes());

                        GenerateObject(type, schema, schemaResolver, schemaDefinitionAppender);
                    }
                    else
                    {
                        schema.SchemaReference = Generate <JsonSchema4>(type, parentAttributes, schemaResolver, schemaDefinitionAppender);
                        return(schema);
                    }
                }
            }
            else if (type.GetTypeInfo().IsEnum)
            {
                var isIntegerEnumeration = typeDescription.Type == JsonObjectType.Integer;
                if (schemaResolver.HasSchema(type, isIntegerEnumeration))
                {
                    schema.SchemaReference = schemaResolver.GetSchema(type, isIntegerEnumeration);
                    return(schema);
                }

                if (schema.GetType() == typeof(JsonSchema4))
                {
                    LoadEnumerations(type, schema, typeDescription);

                    typeDescription.ApplyType(schema);

                    schema.TypeNameRaw = ReflectionExtensions.GetSafeTypeName(type);
                    schema.Description = type.GetXmlSummary();

                    schemaResolver.AddSchema(type, isIntegerEnumeration, schema);
                }
                else
                {
                    schema.SchemaReference = Generate <JsonSchema4>(type, parentAttributes, schemaResolver, schemaDefinitionAppender);
                    return(schema);
                }
            }
            else if (typeDescription.Type.HasFlag(JsonObjectType.Array))
            {
                typeDescription.ApplyType(schema);

                var itemType = type.GetEnumerableItemType();
                if (itemType == null)
                {
                    var jsonSchemaAttribute = type.GetTypeInfo().GetCustomAttribute <JsonSchemaAttribute>();
                    if (jsonSchemaAttribute?.ArrayItem != null)
                    {
                        schema.Item = Generate(jsonSchemaAttribute.ArrayItem, schemaResolver, schemaDefinitionAppender);
                    }
                    else
                    {
                        schema.Item = JsonSchema4.CreateAnySchema();
                    }
                }
                else
                {
                    if (itemType.GetTypeInfo().IsEnum)
                    {
                        schema.Item = new JsonSchema4 {
                            SchemaReference = Generate(itemType, schemaResolver, schemaDefinitionAppender)
                        }
                    }
                    ;
                    else
                    {
                        schema.Item = Generate(itemType, schemaResolver, schemaDefinitionAppender);
                    }
                }
            }
            else
            {
                typeDescription.ApplyType(schema);
            }

            return(schema);
        }
Exemplo n.º 10
0
        /// <summary>Applies the property annotations to the JSON property.</summary>
        /// <param name="jsonProperty">The JSON property.</param>
        /// <param name="parentType">The type of the parent.</param>
        /// <param name="attributes">The attributes.</param>
        /// <param name="propertyTypeDescription">The property type description.</param>
        public void ApplyPropertyAnnotations(JsonSchema4 jsonProperty, Type parentType, IList <Attribute> attributes,
                                             JsonObjectTypeDescription propertyTypeDescription)
        {
            // TODO: Refactor out

            dynamic displayAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.DataAnnotations.DisplayAttribute");

            if (displayAttribute != null && displayAttribute.Name != null)
            {
                jsonProperty.Title = displayAttribute.Name;
            }

            dynamic defaultValueAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.DefaultValueAttribute");

            if (defaultValueAttribute != null && defaultValueAttribute.Value != null)
            {
                jsonProperty.Default = ConvertDefaultValue(parentType, attributes, defaultValueAttribute);
            }

            dynamic regexAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.DataAnnotations.RegularExpressionAttribute");

            if (regexAttribute != null)
            {
                jsonProperty.Pattern = regexAttribute.Pattern;
            }

            if (propertyTypeDescription.Type == JsonObjectType.Number ||
                propertyTypeDescription.Type == JsonObjectType.Integer)
            {
                dynamic rangeAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.DataAnnotations.RangeAttribute");
                if (rangeAttribute != null)
                {
                    if (rangeAttribute.Minimum != null && rangeAttribute.Minimum > double.MinValue)
                    {
                        jsonProperty.Minimum = (decimal?)(double)rangeAttribute.Minimum;
                    }
                    if (rangeAttribute.Maximum != null && rangeAttribute.Maximum < double.MaxValue)
                    {
                        jsonProperty.Maximum = (decimal?)(double)rangeAttribute.Maximum;
                    }
                }

                var multipleOfAttribute = attributes.OfType <MultipleOfAttribute>().SingleOrDefault();
                if (multipleOfAttribute != null)
                {
                    jsonProperty.MultipleOf = multipleOfAttribute.MultipleOf;
                }
            }

            dynamic minLengthAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.DataAnnotations.MinLengthAttribute");

            if (minLengthAttribute != null && minLengthAttribute.Length != null)
            {
                if (propertyTypeDescription.Type == JsonObjectType.String)
                {
                    jsonProperty.MinLength = minLengthAttribute.Length;
                }
                else if (propertyTypeDescription.Type == JsonObjectType.Array)
                {
                    jsonProperty.MinItems = minLengthAttribute.Length;
                }
            }

            dynamic maxLengthAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.DataAnnotations.MaxLengthAttribute");

            if (maxLengthAttribute != null && maxLengthAttribute.Length != null)
            {
                if (propertyTypeDescription.Type == JsonObjectType.String)
                {
                    jsonProperty.MaxLength = maxLengthAttribute.Length;
                }
                else if (propertyTypeDescription.Type == JsonObjectType.Array)
                {
                    jsonProperty.MaxItems = maxLengthAttribute.Length;
                }
            }

            dynamic stringLengthAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.DataAnnotations.StringLengthAttribute");

            if (stringLengthAttribute != null)
            {
                if (propertyTypeDescription.Type == JsonObjectType.String)
                {
                    jsonProperty.MinLength = stringLengthAttribute.MinimumLength;
                    jsonProperty.MaxLength = stringLengthAttribute.MaximumLength;
                }
            }

            dynamic dataTypeAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.DataAnnotations.DataTypeAttribute");

            if (dataTypeAttribute != null)
            {
                var dataType = dataTypeAttribute.DataType.ToString();
                if (DataTypeFormats.ContainsKey(dataType))
                {
                    jsonProperty.Format = DataTypeFormats[dataType];
                }
            }
        }
Exemplo n.º 11
0
        private void LoadPropertyOrField(MemberInfo property, Type propertyType, Type parentType, JsonSchema4 parentSchema, ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            var attributes = property.GetCustomAttributes(inherit: true).OfType <Attribute>().ToArray();
            var propertyTypeDescription = JsonObjectTypeDescription.FromType(propertyType, attributes, Settings.DefaultEnumHandling);

            if (IsPropertyIgnored(parentType, attributes) == false)
            {
                JsonProperty jsonProperty;

                if (propertyType.Name == "Nullable`1")
#if !LEGACY
                { propertyType = propertyType.GenericTypeArguments[0]; }
#else
                { propertyType = propertyType.GetGenericArguments()[0]; }
#endif

                var requiresSchemaReference = RequiresSchemaReference(propertyType, attributes);
                if (requiresSchemaReference)
                {
                    var propertySchema = Generate <JsonSchema4>(propertyType, attributes, schemaResolver, schemaDefinitionAppender);

                    // The schema is automatically added to Definitions if it is missing in JsonPathUtilities.GetJsonPath()
                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        jsonProperty = new JsonProperty();
                        jsonProperty.OneOf.Add(new JsonSchema4
                        {
                            SchemaReference = propertySchema.ActualSchema
                        });
                    }
                    else
                    {
                        jsonProperty = new JsonProperty
                        {
                            SchemaReference = propertySchema.ActualSchema
                        };
                    }
                }
                else
                {
                    jsonProperty = Generate <JsonProperty>(propertyType, attributes, schemaResolver, schemaDefinitionAppender);
                }

                var propertyName = JsonPathUtilities.GetPropertyName(property, Settings.DefaultPropertyNameHandling);
                if (parentSchema.Properties.ContainsKey(propertyName))
                {
                    throw new InvalidOperationException("The JSON property '" + propertyName + "' is defined multiple times on type '" + parentType.FullName + "'.");
                }

                parentSchema.Properties.Add(propertyName, jsonProperty);

                var requiredAttribute     = attributes.TryGetIfAssignableTo("System.ComponentModel.DataAnnotations.RequiredAttribute");
                var jsonPropertyAttribute = attributes.OfType <JsonPropertyAttribute>().SingleOrDefault();

                var hasJsonNetAttributeRequired = jsonPropertyAttribute != null && (
                    jsonPropertyAttribute.Required == Required.Always ||
                    jsonPropertyAttribute.Required == Required.AllowNull);

                var isDataContractMemberRequired = GetDataMemberAttribute(parentType, attributes)?.IsRequired == true;

                var hasRequiredAttribute = requiredAttribute != null;
                if (hasRequiredAttribute || isDataContractMemberRequired || hasJsonNetAttributeRequired)
                {
                    parentSchema.RequiredProperties.Add(propertyName);
                }

                var isJsonNetAttributeNullable = jsonPropertyAttribute != null && jsonPropertyAttribute.Required == Required.AllowNull;

                var isNullable = !hasRequiredAttribute && !isDataContractMemberRequired && (propertyTypeDescription.IsNullable || isJsonNetAttributeNullable);
                if (isNullable)
                {
                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        if (requiresSchemaReference)
                        {
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.Null
                            });
                        }
                        else if (jsonProperty.Type == JsonObjectType.None)
                        {
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.None
                            });
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.Null
                            });
                        }
                        else
                        {
                            jsonProperty.Type = jsonProperty.Type | JsonObjectType.Null;
                        }
                    }
                }
                else if (Settings.NullHandling == NullHandling.Swagger)
                {
                    if (!parentSchema.RequiredProperties.Contains(propertyName))
                    {
                        parentSchema.RequiredProperties.Add(propertyName);
                    }
                }

                dynamic readOnlyAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.ReadOnlyAttribute");
                if (readOnlyAttribute != null)
                {
                    jsonProperty.IsReadOnly = readOnlyAttribute.IsReadOnly;
                }

                jsonProperty.Description = GetDescription(property, attributes);

                ApplyPropertyAnnotations(jsonProperty, parentType, attributes, propertyTypeDescription);
            }
        }
Exemplo n.º 12
0
        /// <summary>Generates a <see cref="JsonSchema4" /> object for the given type and adds the mapping to the given resolver.</summary>
        /// <param name="type">The type.</param>
        /// <param name="rootSchema">The root schema.</param>
        /// <param name="parentAttributes">The parent property or parameter attributes.</param>
        /// <param name="schemaDefinitionAppender">The schema definition appender.</param>
        /// <param name="schemaResolver">The schema resolver.</param>
        /// <returns>The schema.</returns>
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        public TSchemaType Generate <TSchemaType>(Type type, JsonSchema4 rootSchema, IEnumerable <Attribute> parentAttributes, ISchemaDefinitionAppender schemaDefinitionAppender, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var schema = HandleSpecialTypes <TSchemaType>(type);

            if (schema != null)
            {
                return(schema);
            }

            schema = new TSchemaType();

            if (rootSchema == null)
            {
                rootSchema = schema;
            }

            var typeDescription = JsonObjectTypeDescription.FromType(type, parentAttributes, Settings.DefaultEnumHandling);

            typeDescription.ApplyType(schema);

            ApplyExtensionDataAttributes(schema, type, parentAttributes);

            if (schema.Type.HasFlag(JsonObjectType.Object))
            {
                if (typeDescription.IsDictionary)
                {
                    GenerateDictionary(type, rootSchema, schema, schemaDefinitionAppender, schemaResolver);
                }
                else
                {
                    schema.TypeNameRaw = GetTypeName(type);
                    if (schemaResolver.HasSchema(type, false))
                    {
                        schema.SchemaReference = schemaResolver.GetSchema(type, false);
                        return(schema);
                    }

                    if (schema.GetType() == typeof(JsonSchema4))
                    {
                        schema.Description = GetDescription(type.GetTypeInfo(), type.GetTypeInfo().GetCustomAttributes());
                        GenerateObject(type, schema, rootSchema, schemaDefinitionAppender, schemaResolver);
                    }
                    else
                    {
                        schema.SchemaReference = Generate(type, rootSchema, parentAttributes, schemaDefinitionAppender, schemaResolver);
                        return(schema);
                    }
                }
            }
            else if (type.GetTypeInfo().IsEnum)
            {
                var isIntegerEnumeration = typeDescription.Type == JsonObjectType.Integer;
                if (schemaResolver.HasSchema(type, isIntegerEnumeration))
                {
                    schema.Type            = typeDescription.Type;
                    schema.SchemaReference = schemaResolver.GetSchema(type, isIntegerEnumeration);
                    return(schema);
                }

                if (schema.GetType() == typeof(JsonSchema4))
                {
                    LoadEnumerations(type, schema, typeDescription);

                    schema.TypeNameRaw = GetTypeName(type);
                    schema.Description = type.GetXmlDocumentation();
                    schemaResolver.AddSchema(type, isIntegerEnumeration, schema);
                }
                else
                {
                    schema.SchemaReference = Generate(type, rootSchema, parentAttributes, schemaDefinitionAppender, schemaResolver);
                    return(schema);
                }
            }
            else if (schema.Type.HasFlag(JsonObjectType.Array))
            {
                schema.Type = JsonObjectType.Array;

                var genericTypeArguments = GetGenericTypeArguments(type);
                var itemType             = genericTypeArguments.Length == 0 ? type.GetElementType() : genericTypeArguments[0];
                if (itemType == null)
                {
                    schema.Item = JsonSchema4.CreateAnySchema();
                }
                else
                {
                    schema.Item = Generate(itemType, rootSchema, null, schemaDefinitionAppender, schemaResolver);
                }
            }

            return(schema);
        }
Exemplo n.º 13
0
        /// <summary></summary>
        /// <param name="jsonProperty"></param>
        /// <param name="attributes"></param>
        /// <param name="propertyTypeDescription"></param>
        public void ApplyPropertyAnnotations(JsonSchema4 jsonProperty, IEnumerable <Attribute> attributes, JsonObjectTypeDescription propertyTypeDescription)
        {
            dynamic displayAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.DisplayAttribute");

            if (displayAttribute != null && displayAttribute.Name != null)
            {
                jsonProperty.Title = displayAttribute.Name;
            }

            dynamic defaultValueAttribute = TryGetAttribute(attributes, "System.ComponentModel.DefaultValueAttribute");

            if (defaultValueAttribute != null && defaultValueAttribute.Value != null)
            {
                jsonProperty.Default = defaultValueAttribute.Value;
            }

            dynamic regexAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RegularExpressionAttribute");

            if (regexAttribute != null)
            {
                jsonProperty.Pattern = regexAttribute.Pattern;
            }

            if (propertyTypeDescription.Type == JsonObjectType.Number || propertyTypeDescription.Type == JsonObjectType.Integer)
            {
                dynamic rangeAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RangeAttribute");
                if (rangeAttribute != null)
                {
                    if (rangeAttribute.Minimum != null)
                    {
                        jsonProperty.Minimum = rangeAttribute.Minimum;
                    }
                    if (rangeAttribute.Maximum != null)
                    {
                        jsonProperty.Maximum = rangeAttribute.Maximum;
                    }
                }

                var multipleOfAttribute = attributes.OfType <MultipleOfAttribute>().SingleOrDefault();
                if (multipleOfAttribute != null)
                {
                    jsonProperty.MultipleOf = multipleOfAttribute.MultipleOf;
                }
            }

            dynamic minLengthAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.MinLengthAttribute");

            if (minLengthAttribute != null && minLengthAttribute.Length != null)
            {
                if (propertyTypeDescription.Type == JsonObjectType.String)
                {
                    jsonProperty.MinLength = minLengthAttribute.Length;
                }
                else if (propertyTypeDescription.Type == JsonObjectType.Array)
                {
                    jsonProperty.MinItems = minLengthAttribute.Length;
                }
            }

            dynamic maxLengthAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.MaxLengthAttribute");

            if (maxLengthAttribute != null && maxLengthAttribute.Length != null)
            {
                if (propertyTypeDescription.Type == JsonObjectType.String)
                {
                    jsonProperty.MaxLength = maxLengthAttribute.Length;
                }
                else if (propertyTypeDescription.Type == JsonObjectType.Array)
                {
                    jsonProperty.MaxItems = maxLengthAttribute.Length;
                }
            }
        }
Exemplo n.º 14
0
        private void LoadProperty(Type parentType, PropertyInfo property, JsonSchema4 parentSchema, JsonSchema4 rootSchema,
                                  ISchemaDefinitionAppender schemaDefinitionAppender, ISchemaResolver schemaResolver)
        {
            var propertyType            = property.PropertyType;
            var propertyTypeDescription = JsonObjectTypeDescription.FromType(propertyType, property.GetCustomAttributes(), Settings.DefaultEnumHandling);

            var attributes = property.GetCustomAttributes().ToArray();

            if (IsPropertyIgnored(parentType, attributes) == false)
            {
                JsonProperty jsonProperty;

                if (propertyType.Name == "Nullable`1")
                {
                    propertyType = propertyType.GenericTypeArguments[0];
                }

                var useSchemaReference = !propertyTypeDescription.IsDictionary && (propertyTypeDescription.Type.HasFlag(JsonObjectType.Object) || propertyTypeDescription.IsEnum);
                if (useSchemaReference)
                {
                    // schema is automatically added to Definitions if it is missing in JsonPathUtilities.GetJsonPath()

                    var propertySchema = Generate(propertyType, rootSchema,
                                                  property.GetCustomAttributes(), schemaDefinitionAppender, schemaResolver);

                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        jsonProperty = new JsonProperty();
                        jsonProperty.OneOf.Add(new JsonSchema4
                        {
                            SchemaReference = propertySchema.ActualSchema
                        });
                    }
                    else
                    {
                        jsonProperty = new JsonProperty
                        {
                            SchemaReference = propertySchema.ActualSchema
                        };
                    }
                }
                else
                {
                    jsonProperty = Generate <JsonProperty>(propertyType, rootSchema, property.GetCustomAttributes(), schemaDefinitionAppender, schemaResolver);
                    propertyTypeDescription.ApplyType(jsonProperty);
                }

                var propertyName = JsonPathUtilities.GetPropertyName(property);
                parentSchema.Properties.Add(propertyName, jsonProperty);

                var requiredAttribute     = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RequiredAttribute");
                var jsonPropertyAttribute = property.GetCustomAttribute <JsonPropertyAttribute>();

                var hasJsonNetAttributeRequired = jsonPropertyAttribute != null && (
                    jsonPropertyAttribute.Required == Required.Always ||
                    jsonPropertyAttribute.Required == Required.AllowNull);

                var hasRequiredAttribute = requiredAttribute != null;
                if (hasRequiredAttribute || hasJsonNetAttributeRequired)
                {
                    parentSchema.RequiredProperties.Add(propertyName);
                }

                var isJsonNetAttributeNullable = jsonPropertyAttribute != null && jsonPropertyAttribute.Required == Required.AllowNull;

                var isNullable = !hasRequiredAttribute && (propertyTypeDescription.IsNullable || isJsonNetAttributeNullable);
                if (isNullable)
                {
                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        if (useSchemaReference)
                        {
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.Null
                            });
                        }
                        else
                        {
                            jsonProperty.Type = jsonProperty.Type | JsonObjectType.Null;
                        }
                    }
                }
                else if (Settings.NullHandling == NullHandling.Swagger)
                {
                    if (!parentSchema.RequiredProperties.Contains(propertyName))
                    {
                        parentSchema.RequiredProperties.Add(propertyName);
                    }
                }

                dynamic readOnlyAttribute = TryGetAttribute(attributes, "System.ComponentModel.ReadOnlyAttribute");
                if (readOnlyAttribute != null)
                {
                    jsonProperty.IsReadOnly = readOnlyAttribute.IsReadOnly;
                }

                jsonProperty.Description = GetDescription(property, attributes);

                ApplyPropertyAnnotations(jsonProperty, attributes, propertyTypeDescription);
            }
        }
Exemplo n.º 15
0
        private async Task LoadPropertyOrFieldAsync(Newtonsoft.Json.Serialization.JsonProperty property, MemberInfo propertyInfo, Type parentType, JsonSchema4 parentSchema, JsonSchemaResolver schemaResolver)
        {
            var propertyType            = property.PropertyType;
            var attributes              = property.AttributeProvider.GetAttributes(true).ToArray();
            var propertyTypeDescription = JsonObjectTypeDescription.FromType(propertyType, ResolveContract(propertyType), null, Settings.DefaultEnumHandling);

            if (property.Ignored == false)
            {
                JsonProperty jsonProperty;

                if (propertyType.Name == "Nullable`1")
#if !LEGACY
                { propertyType = propertyType.GenericTypeArguments[0]; }
#else
                { propertyType = propertyType.GetGenericArguments()[0]; }
#endif

                var requiresSchemaReference = RequiresSchemaReference(propertyType, attributes);
                if (requiresSchemaReference)
                {
                    var propertySchema = await GenerateAsync(propertyType, attributes, schemaResolver).ConfigureAwait(false);

                    // The schema is automatically added to Definitions if it is missing in JsonPathUtilities.GetJsonPath()
                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        jsonProperty = new JsonProperty();
                        jsonProperty.OneOf.Add(new JsonSchema4
                        {
                            SchemaReference = propertySchema.ActualSchema
                        });
                    }
                    else
                    {
                        jsonProperty = new JsonProperty
                        {
                            SchemaReference = propertySchema.ActualSchema
                        };
                    }
                }
                else
                {
                    jsonProperty = await GenerateAsync <JsonProperty>(propertyType, attributes, schemaResolver).ConfigureAwait(false);
                }

                var contractResolver = Settings.ActualContractResolver as DefaultContractResolver;
                var propertyName     = contractResolver != null?
                                       contractResolver.GetResolvedPropertyName(property.PropertyName) :
                                           property.PropertyName;

                if (parentSchema.Properties.ContainsKey(propertyName))
                {
                    throw new InvalidOperationException("The JSON property '" + propertyName + "' is defined multiple times on type '" + parentType.FullName + "'.");
                }

                if (Settings.GenerateXmlObjects)
                {
                    jsonProperty.GenerateXmlObjectForProperty(parentType, propertyName, attributes);
                }

                parentSchema.Properties.Add(propertyName, jsonProperty);

                var requiredAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.DataAnnotations.RequiredAttribute");

                var hasJsonNetAttributeRequired  = property.Required == Required.Always || property.Required == Required.AllowNull;
                var isDataContractMemberRequired = GetDataMemberAttribute(parentType, attributes)?.IsRequired == true;

                var hasRequiredAttribute = requiredAttribute != null;
                if (hasRequiredAttribute || isDataContractMemberRequired || hasJsonNetAttributeRequired)
                {
                    parentSchema.RequiredProperties.Add(propertyName);
                }

                var isNullable = propertyTypeDescription.IsNullable &&
                                 hasRequiredAttribute == false &&
                                 isDataContractMemberRequired == false &&
                                 (property.Required == Required.Default || property.Required == Required.AllowNull);

                if (isNullable)
                {
                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        if (requiresSchemaReference)
                        {
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.Null
                            });
                        }
                        else if (jsonProperty.Type == JsonObjectType.None)
                        {
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.None
                            });
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.Null
                            });
                        }
                        else
                        {
                            jsonProperty.Type = jsonProperty.Type | JsonObjectType.Null;
                        }
                    }
                }
                else if (Settings.NullHandling == NullHandling.Swagger)
                {
                    if (!parentSchema.RequiredProperties.Contains(propertyName))
                    {
                        parentSchema.RequiredProperties.Add(propertyName);
                    }
                }

                dynamic readOnlyAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.ReadOnlyAttribute");
                if (readOnlyAttribute != null)
                {
                    jsonProperty.IsReadOnly = readOnlyAttribute.IsReadOnly;
                }

                jsonProperty.Description = await propertyInfo.GetDescriptionAsync(attributes).ConfigureAwait(false);

                ApplyPropertyAnnotations(jsonProperty, property, parentType, attributes, propertyTypeDescription);
            }
        }
Exemplo n.º 16
0
        /// <summary>Generates a <see cref="JsonSchema4" /> object for the given type and adds the mapping to the given resolver.</summary>
        /// <typeparam name="TSchemaType">The type of the schema.</typeparam>
        /// <param name="type">The type.</param>
        /// <param name="parentAttributes">The parent property or parameter attributes.</param>
        /// <param name="schema">The schema.</param>
        /// <param name="schemaResolver">The schema resolver.</param>
        /// <returns>The schema.</returns>
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        public virtual async Task GenerateAsync <TSchemaType>(Type type, IEnumerable <Attribute> parentAttributes, TSchemaType schema, JsonSchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            if (await TryHandleSpecialTypesAsync(type, schema, schemaResolver, parentAttributes))
            {
                await ApplySchemaProcessorsAsync(schema, schemaResolver);

                return;
            }

            if (schemaResolver.RootObject == schema)
            {
                schema.Title = Settings.SchemaNameGenerator.Generate(type);
            }

            ApplyExtensionDataAttributes(type, schema, parentAttributes);

            var contract        = ResolveContract(type);
            var typeDescription = JsonObjectTypeDescription.FromType(type, contract, parentAttributes, Settings.DefaultEnumHandling);

            if (typeDescription.Type.HasFlag(JsonObjectType.Object))
            {
                if (typeDescription.IsDictionary)
                {
                    typeDescription.ApplyType(schema);
                    await GenerateDictionaryAsync(type, schema, schemaResolver).ConfigureAwait(false);
                }
                else
                {
                    if (schemaResolver.HasSchema(type, false))
                    {
                        schema.SchemaReference = schemaResolver.GetSchema(type, false);
                    }
                    else if (schema.GetType() == typeof(JsonSchema4))
                    {
                        typeDescription.ApplyType(schema);
                        schema.Description = await type.GetTypeInfo().GetDescriptionAsync(type.GetTypeInfo().GetCustomAttributes()).ConfigureAwait(false);
                        await GenerateObjectAsync(type, contract, schema, schemaResolver).ConfigureAwait(false);
                    }
                    else
                    {
                        schema.SchemaReference = await GenerateAsync(type, parentAttributes, schemaResolver).ConfigureAwait(false);
                    }
                }
            }
            else if (type.GetTypeInfo().IsEnum)
            {
                var isIntegerEnumeration = typeDescription.Type == JsonObjectType.Integer;
                if (schemaResolver.HasSchema(type, isIntegerEnumeration))
                {
                    schema.SchemaReference = schemaResolver.GetSchema(type, isIntegerEnumeration);
                }
                else if (schema.GetType() == typeof(JsonSchema4))
                {
                    LoadEnumerations(type, schema, typeDescription);

                    typeDescription.ApplyType(schema);
                    schema.Description = await type.GetXmlSummaryAsync().ConfigureAwait(false);

                    schemaResolver.AddSchema(type, isIntegerEnumeration, schema);
                }
                else
                {
                    schema.SchemaReference = await GenerateAsync(type, parentAttributes, schemaResolver).ConfigureAwait(false);
                }
            }
            else if (typeDescription.Type.HasFlag(JsonObjectType.Array))
            {
                typeDescription.ApplyType(schema);

                var itemType = type.GetEnumerableItemType();
                if (itemType != null)
                {
                    schema.Item = await GenerateWithReferenceAsync(schemaResolver, itemType).ConfigureAwait(false);
                }
                else
                {
                    schema.Item = JsonSchema4.CreateAnySchema();
                }
            }
            else
            {
                typeDescription.ApplyType(schema);
            }

            await ApplySchemaProcessorsAsync(schema, schemaResolver);
        }