private static TypeSchemaKey CreateKey(Required valueRequired, JsonProperty memberProperty, JsonContract contract)
        {
            int?minLength = DataAnnotationHelpers.GetMinLength(memberProperty);
            int?maxLength = DataAnnotationHelpers.GetMaxLength(memberProperty);

            Required resolvedRequired;

            switch (valueRequired)
            {
            case Required.Default:
            case Required.AllowNull:
                resolvedRequired = Required.AllowNull;
                break;

            case Required.Always:
            case Required.DisallowNull:
                resolvedRequired = Required.DisallowNull;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(valueRequired));
            }

            TypeSchemaKey key = new TypeSchemaKey(contract.UnderlyingType, resolvedRequired, minLength, maxLength);

            return(key);
        }
        private static TypeSchemaKey CreateKey(Required valueRequired, JsonProperty memberProperty, JsonContract contract)
        {
            int?minLength = DataAnnotationHelpers.GetMinLength(memberProperty);
            int?maxLength = DataAnnotationHelpers.GetMaxLength(memberProperty);

            TypeSchemaKey key = new TypeSchemaKey(contract.UnderlyingType, valueRequired, minLength, maxLength);

            return(key);
        }
예제 #3
0
        private void PopulatePrimativeSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            JSchemaType type = GetJSchemaType(contract.UnderlyingType, valueRequired);

            if (type != Constants.AnyType)
            {
                schema.Type = GetJSchemaType(contract.UnderlyingType, valueRequired);
            }

            if (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.String))
            {
                if (DataAnnotationHelpers.GetStringLength(memberProperty, out int minimumLength, out int maximumLength))
                {
                    schema.MinimumLength = minimumLength;
                    schema.MaximumLength = maximumLength;
                }
                else
                {
                    schema.MinimumLength = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumLength = DataAnnotationHelpers.GetMaxLength(memberProperty);
                }

                schema.Pattern = DataAnnotationHelpers.GetPattern(memberProperty);
                schema.Format  = DataAnnotationHelpers.GetFormat(memberProperty);

                // no format specified, derive from type
                if (schema.Format == null)
                {
                    if (contract.NonNullableUnderlyingType == typeof(DateTime) ||
                        contract.NonNullableUnderlyingType == typeof(DateTimeOffset))
                    {
                        schema.Format = Constants.Formats.DateTime;
                    }
                    else if (contract.NonNullableUnderlyingType == typeof(Uri))
                    {
                        schema.Format = Constants.Formats.Uri;
                    }
                }
            }
        private void PopulatePrimativeSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            JSchemaType type = GetJSchemaType(contract.UnderlyingType, valueRequired);

            if (type != Constants.AnyType)
            {
                schema.Type = GetJSchemaType(contract.UnderlyingType, valueRequired);
            }

            if (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.String))
            {
                int minimumLength;
                int maximumLength;
                if (DataAnnotationHelpers.GetStringLength(memberProperty, out minimumLength, out maximumLength))
                {
                    schema.MinimumLength = minimumLength;
                    schema.MaximumLength = maximumLength;
                }
                else
                {
                    schema.MinimumLength = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumLength = DataAnnotationHelpers.GetMaxLength(memberProperty);
                }

                schema.Pattern = DataAnnotationHelpers.GetPattern(memberProperty);
                schema.Format  = DataAnnotationHelpers.GetFormat(memberProperty);
            }
            if (JSchemaTypeHelpers.HasFlag(type, JSchemaType.Number) || JSchemaTypeHelpers.HasFlag(type, JSchemaType.Integer))
            {
                double minimum;
                double maximum;
                if (DataAnnotationHelpers.GetRange(memberProperty, out minimum, out maximum))
                {
                    schema.Minimum = minimum;
                    schema.Maximum = maximum;
                }
            }

            if (JSchemaTypeHelpers.HasFlag(type, JSchemaType.Integer) &&
                contract.NonNullableUnderlyingType.IsEnum() &&
                ReflectionUtils.GetAttribute <FlagsAttribute>(contract.NonNullableUnderlyingType) == null)
            {
                if ((type & JSchemaType.Null) == JSchemaType.Null)
                {
                    schema.Enum.Add(JValue.CreateNull());
                }

                IList <EnumValue <long> > enumValues = EnumUtils.GetNamesAndValues <long>(contract.NonNullableUnderlyingType);
                foreach (EnumValue <long> enumValue in enumValues)
                {
                    JToken value = JToken.FromObject(enumValue.Value);

                    schema.Enum.Add(value);
                }
            }

            Type enumDataType = DataAnnotationHelpers.GetEnumDataType(memberProperty);

            if (enumDataType != null && CollectionUtils.IsNullOrEmpty(schema._enum))
            {
                IList <EnumValue <long> > enumValues = EnumUtils.GetNamesAndValues <long>(enumDataType);
                foreach (EnumValue <long> enumValue in enumValues)
                {
                    JToken value = (JSchemaTypeHelpers.HasFlag(type, JSchemaType.String))
                        ? enumValue.Name
                        : JToken.FromObject(enumValue.Value);

                    schema.Enum.Add(value);
                }
            }
        }
        private void PopulateSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            schema.Title       = GetTitle(contract.NonNullableUnderlyingType);
            schema.Description = GetDescription(contract.NonNullableUnderlyingType);

            JsonConverter converter;

            if (contract.Converter != null && contract.Converter.CanWrite)
            {
                converter = contract.Converter;
            }
            else if (contract.InternalConverter != null && contract.InternalConverter.CanWrite)
            {
                converter = contract.InternalConverter;
            }
            else
            {
                converter = null;
            }

            if (converter != null)
            {
                schema.Type = null;
            }
            else
            {
                switch (contract.ContractType)
                {
                case JsonContractType.Object:
                    if (contract.NonNullableUnderlyingType == typeof(object))
                    {
                        PopulatePrimativeSchema(schema, contract, memberProperty, valueRequired);
                    }
                    else
                    {
                        if (schema.Id == null)
                        {
                            schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                        }

                        schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                        GenerateObjectSchema(schema, contract.NonNullableUnderlyingType, (JsonObjectContract)contract);
                    }
                    break;

                case JsonContractType.Array:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                    }

                    schema.Type         = AddNullType(JSchemaType.Array, valueRequired);
                    schema.MinimumItems = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumItems = DataAnnotationHelpers.GetMaxLength(memberProperty);

                    JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetCachedAttribute <JsonArrayAttribute>(contract.NonNullableUnderlyingType);

                    Required?required = null;
                    if (arrayAttribute != null && !arrayAttribute.AllowNullItems)
                    {
                        required = Required.Always;
                    }

                    Type collectionItemType = ReflectionUtils.GetCollectionItemType(contract.NonNullableUnderlyingType);
                    if (collectionItemType != null)
                    {
                        schema.Items.Add(GenerateInternal(collectionItemType, required, null, (JsonArrayContract)contract, null));
                    }
                    break;

                case JsonContractType.Primitive:
                    PopulatePrimativeSchema(schema, contract, memberProperty, valueRequired);
                    break;

                case JsonContractType.String:
                    JSchemaType schemaType = (!ReflectionUtils.IsNullable(contract.UnderlyingType))
                            ? JSchemaType.String
                            : AddNullType(JSchemaType.String, valueRequired);

                    schema.Type          = schemaType;
                    schema.MinimumLength = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumLength = DataAnnotationHelpers.GetMaxLength(memberProperty);
                    break;

                case JsonContractType.Dictionary:
                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.MinimumProperties = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumProperties = DataAnnotationHelpers.GetMaxLength(memberProperty);

                    Type keyType;
                    Type valueType;
                    ReflectionUtils.GetDictionaryKeyValueTypes(contract.NonNullableUnderlyingType, out keyType, out valueType);

                    if (keyType != null)
                    {
                        JsonContract keyContract = _generator.ContractResolver.ResolveContract(keyType);

                        // can be converted to a string
                        if (keyContract.ContractType == JsonContractType.Primitive)
                        {
                            schema.AdditionalProperties = GenerateInternal(valueType, _generator.DefaultRequired, null, (JsonDictionaryContract)contract, null);
                        }
                    }
                    break;

                case JsonContractType.Serializable:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                    }

                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.AllowAdditionalProperties = true;
                    break;

                case JsonContractType.Dynamic:
                case JsonContractType.Linq:
                    schema.Type = null;
                    break;

                default:
                    throw new JSchemaException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
                }
            }
        }
        private JSchema PopulateSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            schema.Title       = GetTitle(contract.NonNullableUnderlyingType);
            schema.Description = GetDescription(contract.NonNullableUnderlyingType);

            JsonConverter converter = contract.Converter ?? contract.InternalConverter;

            if (converter != null)
            {
                // todo: Add GetSchema to JsonConverter and use here?
                schema.Type = JSchemaType.Any;
            }
            else
            {
                switch (contract.ContractType)
                {
                case JsonContractType.Object:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                    }

                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    GenerateObjectSchema(schema, contract.NonNullableUnderlyingType, (JsonObjectContract)contract);
                    break;

                case JsonContractType.Array:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                    }

                    schema.Type         = AddNullType(JSchemaType.Array, valueRequired);
                    schema.MinimumItems = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumItems = DataAnnotationHelpers.GetMaxLength(memberProperty);

                    JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetCachedAttribute <JsonArrayAttribute>(contract.NonNullableUnderlyingType);
                    bool allowNullItem = (arrayAttribute == null || arrayAttribute.AllowNullItems);

                    Type collectionItemType = ReflectionUtils.GetCollectionItemType(contract.NonNullableUnderlyingType);
                    if (collectionItemType != null)
                    {
                        schema.Items.Add(GenerateInternal(collectionItemType, (!allowNullItem) ? Required.Always : Required.Default, null, (JsonArrayContract)contract));
                    }
                    break;

                case JsonContractType.Primitive:
                    schema.Type = GetJSchemaType(contract.UnderlyingType, valueRequired);

                    if (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.String))
                    {
                        int minimumLength;
                        int maximumLength;
                        if (DataAnnotationHelpers.GetStringLength(memberProperty, out minimumLength, out maximumLength))
                        {
                            schema.MinimumLength = minimumLength;
                            schema.MaximumLength = maximumLength;
                        }
                        else
                        {
                            schema.MinimumLength = DataAnnotationHelpers.GetMinLength(memberProperty);
                            schema.MaximumLength = DataAnnotationHelpers.GetMaxLength(memberProperty);
                        }

                        schema.Pattern = DataAnnotationHelpers.GetPattern(memberProperty);
                        schema.Format  = DataAnnotationHelpers.GetFormat(memberProperty);
                    }
                    if (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.Float) || JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.Integer))
                    {
                        double minimum;
                        double maximum;
                        if (DataAnnotationHelpers.GetRange(memberProperty, out minimum, out maximum))
                        {
                            schema.Minimum = minimum;
                            schema.Maximum = maximum;
                        }
                    }

                    if (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.Integer) &&
                        contract.NonNullableUnderlyingType.IsEnum() &&
                        ReflectionUtils.GetAttribute <FlagsAttribute>(contract.NonNullableUnderlyingType) == null)
                    {
                        IList <EnumValue <long> > enumValues = EnumUtils.GetNamesAndValues <long>(contract.NonNullableUnderlyingType);
                        foreach (EnumValue <long> enumValue in enumValues)
                        {
                            JToken value = JToken.FromObject(enumValue.Value);

                            schema.Enum.Add(value);
                        }
                    }

                    Type enumDataType = DataAnnotationHelpers.GetEnumDataType(memberProperty);
                    if (enumDataType != null && CollectionUtils.IsNullOrEmpty(schema._enum))
                    {
                        IList <EnumValue <long> > enumValues = EnumUtils.GetNamesAndValues <long>(enumDataType);
                        foreach (EnumValue <long> enumValue in enumValues)
                        {
                            JToken value = (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.String))
                                    ? enumValue.Name
                                    : JToken.FromObject(enumValue.Value);

                            schema.Enum.Add(value);
                        }
                    }
                    break;

                case JsonContractType.String:
                    JSchemaType schemaType = (!ReflectionUtils.IsNullable(contract.UnderlyingType))
                            ? JSchemaType.String
                            : AddNullType(JSchemaType.String, valueRequired);

                    schema.Type          = schemaType;
                    schema.MinimumLength = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumLength = DataAnnotationHelpers.GetMaxLength(memberProperty);
                    break;

                case JsonContractType.Dictionary:
                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.MinimumProperties = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumProperties = DataAnnotationHelpers.GetMaxLength(memberProperty);

                    Type keyType;
                    Type valueType;
                    ReflectionUtils.GetDictionaryKeyValueTypes(contract.NonNullableUnderlyingType, out keyType, out valueType);

                    if (keyType != null)
                    {
                        JsonContract keyContract = ContractResolver.ResolveContract(keyType);

                        // can be converted to a string
                        if (keyContract.ContractType == JsonContractType.Primitive)
                        {
                            schema.AdditionalProperties = GenerateInternal(valueType, Required.Default, null, (JsonDictionaryContract)contract);
                        }
                    }
                    break;

                case JsonContractType.Serializable:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                    }

                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.AllowAdditionalProperties = true;
                    break;

                case JsonContractType.Dynamic:
                case JsonContractType.Linq:
                    schema.Type = JSchemaType.Any;
                    break;

                default:
                    throw new JsonException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
                }
            }

            return(schema);
        }