private TypeSchemaKey CreateKey(Required valueRequired, JsonProperty memberProperty, JsonContract contract)
        {
            int?   minLength   = AttributeHelpers.GetMinLength(memberProperty);
            int?   maxLength   = AttributeHelpers.GetMaxLength(memberProperty);
            string title       = GetTitle(contract.NonNullableUnderlyingType, memberProperty);
            string description = GetDescription(contract.NonNullableUnderlyingType, 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, title, description);

            return(key);
        }
Beispiel #2
0
        private void PopulatePrimativeSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            Type        nonNullableUnderlyingType = GetNonNullableUnderlyingType(contract);
            JSchemaType type = GetJSchemaType(contract.UnderlyingType, valueRequired);

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

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

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

                // no format specified, derive from type
                if (schema.Format == null)
                {
                    if (nonNullableUnderlyingType == typeof(DateTime) ||
                        nonNullableUnderlyingType == typeof(DateTimeOffset))
                    {
                        schema.Format = Constants.Formats.DateTime;
                    }
                    else if (nonNullableUnderlyingType == typeof(Uri))
                    {
                        schema.Format = Constants.Formats.Uri;
                    }
                }
            }
        private void PopulateSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            schema.Title       = GetTitle(contract.NonNullableUnderlyingType, memberProperty);
            schema.Description = GetDescription(contract.NonNullableUnderlyingType, memberProperty);

            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 = AttributeHelpers.GetMinLength(memberProperty);
                    schema.MaximumItems = AttributeHelpers.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 = AttributeHelpers.GetMinLength(memberProperty);
                    schema.MaximumLength = AttributeHelpers.GetMaxLength(memberProperty);
                    break;

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

                    ReflectionUtils.GetDictionaryKeyValueTypes(contract.NonNullableUnderlyingType, out Type keyType, out Type 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 void PopulateSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            Type nonNullableUnderlyingType = GetNonNullableUnderlyingType(contract);

            schema.Title       = GetTitle(nonNullableUnderlyingType, memberProperty);
            schema.Description = GetDescription(nonNullableUnderlyingType, memberProperty);

            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)
                {
                case JsonObjectContract objectContract:
                    if (nonNullableUnderlyingType == typeof(object))
                    {
                        PopulatePrimativeSchema(schema, objectContract, memberProperty, valueRequired);
                    }
                    else
                    {
                        if (schema.Id == null)
                        {
                            schema.Id = GetTypeId(nonNullableUnderlyingType, false);
                        }

                        schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                        GenerateObjectSchema(schema, nonNullableUnderlyingType, objectContract);
                    }
                    break;

                case JsonArrayContract arrayContract:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(nonNullableUnderlyingType, false);
                    }

                    schema.Type         = AddNullType(JSchemaType.Array, valueRequired);
                    schema.MinimumItems = AttributeHelpers.GetMinLength(memberProperty);
                    schema.MaximumItems = AttributeHelpers.GetMaxLength(memberProperty);
                    schema.UniqueItems  = ReflectionUtils.IsISetType(nonNullableUnderlyingType) || AttributeHelpers.GetUniqueItems(memberProperty);

                    JsonArrayAttribute arrayAttribute = ReflectionUtils.GetAttribute <JsonArrayAttribute>(nonNullableUnderlyingType);

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

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

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

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

                case JsonPrimitiveContract primitiveContract:
                    PopulatePrimativeSchema(schema, primitiveContract, memberProperty, valueRequired);
                    break;

                case JsonDictionaryContract dictionaryContract:
                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.MinimumProperties = AttributeHelpers.GetMinLength(memberProperty);
                    schema.MaximumProperties = AttributeHelpers.GetMaxLength(memberProperty);

                    ReflectionUtils.GetDictionaryKeyValueTypes(nonNullableUnderlyingType, out Type keyType, out Type valueType);

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

                        // can be converted to a string
                        if (keyContract is JsonPrimitiveContract)
                        {
                            schema.AdditionalProperties = GenerateInternal(valueType, _generator.DefaultRequired, null, dictionaryContract, null);
                        }
                    }
                    break;

#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0
                case JsonISerializableContract serializableContract:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(nonNullableUnderlyingType, false);
                    }

                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.AllowAdditionalProperties = true;
                    break;
#endif
#if !NET35
                case JsonDynamicContract dynamicContract:
#endif
                case JsonLinqContract linqContract:
                    schema.Type = null;
                    break;

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