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)); } } }