/// <summary>Initializes a new instance of the <see cref="SchemaProcessorContext" /> class.</summary> /// <param name="type">The source type.</param> /// <param name="schema">The JSON Schema.</param> /// <param name="resolver">The resolver.</param> /// <param name="generator">The generator.</param> /// <param name="settings">The settings.</param> public SchemaProcessorContext(Type type, JsonSchema schema, JsonSchemaResolver resolver, JsonSchemaGenerator generator, JsonSchemaGeneratorSettings settings) { Type = type; Schema = schema; Resolver = resolver; Generator = generator; Settings = settings; }
static SchemaHelper() { RegexOptions regexOptions = RegexOptions.None; _regex = new Regex(@"\w+\.(entities|links)\.schema\.json", regexOptions); _settings = new NJsonSchema.Generation.JsonSchemaGeneratorSettings() { FlattenInheritanceHierarchy = true, GenerateEnumMappingDescription = true, }; _settings.ActualSerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); }
/// <summary>Creates a <see cref="JsonTypeDescription"/> from a <see cref="Type"/>. </summary> /// <param name="contextualType">The type.</param> /// <param name="defaultReferenceTypeNullHandling">The default reference type null handling used when no nullability information is available.</param> /// <param name="settings">The settings.</param> /// <returns>The <see cref="JsonTypeDescription"/>. </returns> public virtual JsonTypeDescription GetDescription(ContextualType contextualType, ReferenceTypeNullHandling defaultReferenceTypeNullHandling, JsonSchemaGeneratorSettings settings) { var type = contextualType.OriginalType; var isNullable = IsNullable(contextualType, defaultReferenceTypeNullHandling); var jsonSchemaTypeAttribute = contextualType.GetAttribute <JsonSchemaTypeAttribute>(); if (jsonSchemaTypeAttribute != null) { type = jsonSchemaTypeAttribute.Type; contextualType = type.ToContextualType(); if (jsonSchemaTypeAttribute.IsNullableRaw.HasValue) { isNullable = jsonSchemaTypeAttribute.IsNullableRaw.Value; } } var jsonSchemaAttribute = contextualType.GetAttribute <JsonSchemaAttribute>(); if (jsonSchemaAttribute != null) { var classType = jsonSchemaAttribute.Type != JsonObjectType.None ? jsonSchemaAttribute.Type : JsonObjectType.Object; var format = !string.IsNullOrEmpty(jsonSchemaAttribute.Format) ? jsonSchemaAttribute.Format : null; return(JsonTypeDescription.Create(contextualType, classType, isNullable, format)); } if (type.GetTypeInfo().IsEnum) { var isStringEnum = IsStringEnum(contextualType, settings.ActualSerializerSettings); return(JsonTypeDescription.CreateForEnumeration(contextualType, isStringEnum ? JsonObjectType.String : JsonObjectType.Integer, false)); } // Primitive types if (type == typeof(short) || type == typeof(uint) || type == typeof(ushort)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, null)); } if (type == typeof(int)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, JsonFormatStrings.Integer)); } if (type == typeof(long) || type == typeof(ulong)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, JsonFormatStrings.Long)); } if (type == typeof(double)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.Number, false, JsonFormatStrings.Double)); } if (type == typeof(float)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.Number, false, JsonFormatStrings.Float)); } if (type == typeof(decimal)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.Number, false, JsonFormatStrings.Decimal)); } if (type == typeof(bool)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.Boolean, false, null)); } if (type == typeof(string) || type == typeof(Type)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, null)); } if (type == typeof(char)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, null)); } if (type == typeof(Guid)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, JsonFormatStrings.Guid)); } // Date & time types if (type == typeof(DateTime) || type == typeof(DateTimeOffset) || type.FullName == "NodaTime.OffsetDateTime" || type.FullName == "NodaTime.LocalDateTime" || type.FullName == "NodaTime.ZonedDateTime" || type.FullName == "NodaTime.Instant") { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, JsonFormatStrings.DateTime)); } if (type == typeof(TimeSpan) || type.FullName == "NodaTime.Duration") { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, JsonFormatStrings.TimeSpan)); } if (type.FullName == "NodaTime.LocalDate") { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, JsonFormatStrings.Date)); } if (type.FullName == "NodaTime.LocalTime") { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, JsonFormatStrings.Time)); } // Special types if (type == typeof(Uri)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, JsonFormatStrings.Uri)); } if (type == typeof(byte)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, JsonFormatStrings.Byte)); } if (type == typeof(byte[])) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, JsonFormatStrings.Byte)); } if (type.IsAssignableToTypeName(nameof(JArray), TypeNameStyle.Name)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.Array, isNullable, null)); } if (type.IsAssignableToTypeName(nameof(JToken), TypeNameStyle.Name) || type.FullName == "System.Dynamic.ExpandoObject" || type.FullName == "System.Text.Json.JsonElement" || type == typeof(object)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.None, isNullable, null)); } if (IsBinary(contextualType)) { if (settings.SchemaType == SchemaType.Swagger2) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.File, isNullable, null)); } else { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, JsonFormatStrings.Binary)); } } if (contextualType.IsNullableType) { var typeDescription = GetDescription(contextualType.OriginalGenericArguments[0], defaultReferenceTypeNullHandling, settings); typeDescription.IsNullable = true; return(typeDescription); } var contract = settings.ResolveContract(type); if (IsDictionaryType(contextualType) && contract is JsonDictionaryContract) { return(JsonTypeDescription.CreateForDictionary(contextualType, JsonObjectType.Object, isNullable)); } // TODO: Don't trust JsonArrayContract when contextualType is IAsyncEnumerable<T> until it is fixed if (IsIAsyncEnumerableType(contextualType) || (IsArrayType(contextualType) && contract is JsonArrayContract)) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.Array, isNullable, null)); } if (contract is JsonStringContract) { return(JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, null)); } return(JsonTypeDescription.Create(contextualType, JsonObjectType.Object, isNullable, null)); }
/// <summary>Creates a <see cref="JsonTypeDescription"/> from a <see cref="Type"/>. </summary> /// <param name="contextualType">The type.</param> /// <param name="settings">The settings.</param> /// <returns>The <see cref="JsonTypeDescription"/>. </returns> public JsonTypeDescription GetDescription(ContextualType contextualType, JsonSchemaGeneratorSettings settings) { return(GetDescription(contextualType, settings.DefaultReferenceTypeNullHandling, settings)); }
/// <summary>Initializes a new instance of the <see cref="JsonSchemaGenerator"/> class.</summary> /// <param name="settings">The settings.</param> public JsonSchemaGenerator(JsonSchemaGeneratorSettings settings) { Settings = settings; }
/// <summary>Initializes a new instance of the <see cref="JsonSchemaResolver" /> class.</summary> /// <param name="rootObject">The root schema.</param> /// <param name="settings">The settings.</param> public JsonSchemaResolver(object rootObject, JsonSchemaGeneratorSettings settings) : base(rootObject, settings.TypeNameGenerator) { _settings = settings; }
/// <summary>Creates a <see cref="JsonTypeDescription"/> from a <see cref="Type"/>. </summary> /// <param name="type">The type. </param> /// <param name="parentAttributes">The parent's attributes (i.e. parameter or property attributes).</param> /// <param name="defaultReferenceTypeNullHandling">The default reference type null handling used when no nullability information is available.</param> /// <param name="settings">The settings.</param> /// <returns>The <see cref="JsonTypeDescription"/>. </returns> public virtual JsonTypeDescription GetDescription(Type type, IEnumerable <Attribute> parentAttributes, ReferenceTypeNullHandling defaultReferenceTypeNullHandling, JsonSchemaGeneratorSettings settings) { var isNullable = IsNullable(type, parentAttributes, defaultReferenceTypeNullHandling); var jsonSchemaTypeAttribute = type.GetTypeInfo().GetCustomAttribute <JsonSchemaTypeAttribute>() ?? parentAttributes?.OfType <JsonSchemaTypeAttribute>().SingleOrDefault(); if (jsonSchemaTypeAttribute != null) { type = jsonSchemaTypeAttribute.Type; if (jsonSchemaTypeAttribute.IsNullableRaw.HasValue) { isNullable = jsonSchemaTypeAttribute.IsNullableRaw.Value; } } var jsonSchemaAttribute = type.GetTypeInfo().GetCustomAttribute <JsonSchemaAttribute>() ?? parentAttributes?.OfType <JsonSchemaAttribute>().SingleOrDefault(); if (jsonSchemaAttribute != null) { var classType = jsonSchemaAttribute.Type != JsonObjectType.None ? jsonSchemaAttribute.Type : JsonObjectType.Object; var format = !string.IsNullOrEmpty(jsonSchemaAttribute.Format) ? jsonSchemaAttribute.Format : null; return(JsonTypeDescription.Create(type, classType, isNullable, format)); } if (type.GetTypeInfo().IsEnum) { var isStringEnum = IsStringEnum(type, parentAttributes, settings); return(JsonTypeDescription.CreateForEnumeration(type, isStringEnum ? JsonObjectType.String : JsonObjectType.Integer, false)); } if (type == typeof(short) || type == typeof(uint) || type == typeof(ushort)) { return(JsonTypeDescription.Create(type, JsonObjectType.Integer, false, null)); } if (type == typeof(int)) { return(JsonTypeDescription.Create(type, JsonObjectType.Integer, false, JsonFormatStrings.Integer)); } if (type == typeof(long) || type == typeof(ulong)) { return(JsonTypeDescription.Create(type, JsonObjectType.Integer, false, JsonFormatStrings.Long)); } if (type == typeof(double) || type == typeof(float)) { return(JsonTypeDescription.Create(type, JsonObjectType.Number, false, JsonFormatStrings.Double)); } if (type == typeof(decimal)) { return(JsonTypeDescription.Create(type, JsonObjectType.Number, false, JsonFormatStrings.Decimal)); } if (type == typeof(bool)) { return(JsonTypeDescription.Create(type, JsonObjectType.Boolean, false, null)); } if (type == typeof(string) || type == typeof(Type)) { return(JsonTypeDescription.Create(type, JsonObjectType.String, isNullable, null)); } if (type == typeof(char)) { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, null)); } if (type == typeof(Guid)) { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, JsonFormatStrings.Guid)); } if (type == typeof(DateTime) || type == typeof(DateTimeOffset) || type.FullName == "NodaTime.OffsetDateTime" || type.FullName == "NodaTime.LocalDateTime" || type.FullName == "NodaTime.ZonedDateTime" || type.FullName == "NodaTime.Instant") { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, JsonFormatStrings.DateTime)); } if (type == typeof(TimeSpan) || type.FullName == "NodaTime.Duration") { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, JsonFormatStrings.TimeSpan)); } if (type.FullName == "NodaTime.LocalDate") { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, JsonFormatStrings.Date)); } if (type.FullName == "NodaTime.LocalTime") { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, JsonFormatStrings.Time)); } if (type == typeof(Uri)) { return(JsonTypeDescription.Create(type, JsonObjectType.String, isNullable, JsonFormatStrings.Uri)); } if (type == typeof(byte)) { return(JsonTypeDescription.Create(type, JsonObjectType.Integer, false, JsonFormatStrings.Byte)); } if (type == typeof(byte[])) { return(JsonTypeDescription.Create(type, JsonObjectType.String, isNullable, JsonFormatStrings.Byte)); } if (type.IsAssignableTo(nameof(JArray), TypeNameStyle.Name)) { return(JsonTypeDescription.Create(type, JsonObjectType.Array, isNullable, null)); } if (type.IsAssignableTo(nameof(JToken), TypeNameStyle.Name) || type.FullName == "System.Dynamic.ExpandoObject" || type == typeof(object)) { return(JsonTypeDescription.Create(type, JsonObjectType.None, isNullable, null)); } if (IsBinary(type, parentAttributes)) { if (settings.SchemaType == SchemaType.Swagger2) { return(JsonTypeDescription.Create(type, JsonObjectType.File, isNullable, null)); } else { return(JsonTypeDescription.Create(type, JsonObjectType.String, isNullable, JsonFormatStrings.Binary)); } } var contract = settings.ResolveContract(type); if (IsDictionaryType(type, parentAttributes) && contract is JsonDictionaryContract) { return(JsonTypeDescription.CreateForDictionary(type, JsonObjectType.Object, isNullable)); } if (IsArrayType(type, parentAttributes) && contract is JsonArrayContract) { return(JsonTypeDescription.Create(type, JsonObjectType.Array, isNullable, null)); } if (type.Name == "Nullable`1") { #if !LEGACY // Remove JsonSchemaTypeAttributes to avoid stack overflows var typeDescription = GetDescription(type.GenericTypeArguments[0], parentAttributes?.Where(a => !(a is JsonSchemaTypeAttribute)), defaultReferenceTypeNullHandling, settings); #else var typeDescription = GetDescription(type.GetGenericArguments()[0], parentAttributes?.Where(a => !(a is JsonSchemaTypeAttribute)), defaultReferenceTypeNullHandling, settings); #endif typeDescription.IsNullable = true; return(typeDescription); } if (contract is JsonStringContract) { return(JsonTypeDescription.Create(type, JsonObjectType.String, isNullable, null)); } return(JsonTypeDescription.Create(type, JsonObjectType.Object, isNullable, null)); }
private bool IsStringEnum(Type type, IEnumerable <Attribute> parentAttributes, JsonSchemaGeneratorSettings settings) { var hasGlobalStringEnumConverter = settings.ActualSerializerSettings.Converters.OfType <StringEnumConverter>().Any(); var hasStringEnumConverterOnType = HasStringEnumConverter(type.GetTypeInfo().GetCustomAttributes()); var hasStringEnumConverterOnProperty = parentAttributes != null && HasStringEnumConverter(parentAttributes); return(hasGlobalStringEnumConverter || hasStringEnumConverterOnType || hasStringEnumConverterOnProperty); }
/// <summary>Creates a <see cref="JsonTypeDescription"/> from a <see cref="Type"/>. </summary> /// <param name="type">The type. </param> /// <param name="parentAttributes">The parent's attributes (i.e. parameter or property attributes).</param> /// <param name="settings">The settings.</param> /// <returns>The <see cref="JsonTypeDescription"/>. </returns> public JsonTypeDescription GetDescription(Type type, IEnumerable <Attribute> parentAttributes, JsonSchemaGeneratorSettings settings) { return(GetDescription(type, parentAttributes, settings.DefaultReferenceTypeNullHandling, settings)); }
/// <summary>Checks whether a type is nullable.</summary> /// <param name="type">The type.</param> /// <param name="parentAttributes">The parent attributes (e.g. property or parameter attributes).</param> /// <param name="settings">The settings</param> /// <returns>true if the type can be null.</returns> public virtual bool IsNullable(Type type, IEnumerable <Attribute> parentAttributes, JsonSchemaGeneratorSettings settings) { var jsonPropertyAttribute = parentAttributes?.OfType <JsonPropertyAttribute>().SingleOrDefault(); if (jsonPropertyAttribute != null && jsonPropertyAttribute.Required == Required.DisallowNull) { return(false); } if (parentAttributes.TryGetIfAssignableTo("NotNullAttribute", TypeNameStyle.Name) != null) { return(false); } if (parentAttributes.TryGetIfAssignableTo("CanBeNullAttribute", TypeNameStyle.Name) != null) { return(true); } if (type.Name == "Nullable`1") { return(true); } var isValueType = type != typeof(string) && type.GetTypeInfo().IsValueType; return(isValueType == false && settings.DefaultReferenceTypeNullHandling == ReferenceTypeNullHandling.Null); }
/// <summary>Creates a <see cref="JsonTypeDescription"/> from a <see cref="Type"/>. </summary> /// <param name="type">The type. </param> /// <param name="parentAttributes">The parent's attributes (i.e. parameter or property attributes).</param> /// <param name="settings">The settings.</param> /// <returns>The <see cref="JsonTypeDescription"/>. </returns> public virtual JsonTypeDescription GetDescription(Type type, IEnumerable <Attribute> parentAttributes, JsonSchemaGeneratorSettings settings) { if (type.GetTypeInfo().IsEnum) { var isStringEnum = IsStringEnum(type, parentAttributes, settings.DefaultEnumHandling); return(JsonTypeDescription.CreateForEnumeration(type, isStringEnum ? JsonObjectType.String : JsonObjectType.Integer, false)); } if (type == typeof(short) || type == typeof(uint) || type == typeof(ushort)) { return(JsonTypeDescription.Create(type, JsonObjectType.Integer, false, null)); } if (type == typeof(int)) { return(JsonTypeDescription.Create(type, JsonObjectType.Integer, false, JsonFormatStrings.Integer)); } if ((type == typeof(long)) || (type == typeof(ulong))) { return(JsonTypeDescription.Create(type, JsonObjectType.Integer, false, JsonFormatStrings.Long)); } if (type == typeof(double) || type == typeof(float)) { return(JsonTypeDescription.Create(type, JsonObjectType.Number, false, JsonFormatStrings.Double)); } if (type == typeof(decimal)) { return(JsonTypeDescription.Create(type, JsonObjectType.Number, false, JsonFormatStrings.Decimal)); } if (type == typeof(bool)) { return(JsonTypeDescription.Create(type, JsonObjectType.Boolean, false, null)); } var isNullable = IsNullable(type, parentAttributes, settings); if (type == typeof(string) || type == typeof(Type)) { return(JsonTypeDescription.Create(type, JsonObjectType.String, isNullable, null)); } if (type == typeof(char)) { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, null)); } if (type == typeof(Guid)) { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, JsonFormatStrings.Guid)); } if (type == typeof(DateTime) || type == typeof(DateTimeOffset) || type.FullName == "NodaTime.OffsetDateTime" || type.FullName == "NodaTime.ZonedDateTime") { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, JsonFormatStrings.DateTime)); } if (type == typeof(TimeSpan) || type.FullName == "NodaTime.Duration") { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, JsonFormatStrings.TimeSpan)); } if (type.FullName == "NodaTime.LocalDate") { return(JsonTypeDescription.Create(type, JsonObjectType.String, false, JsonFormatStrings.Date)); } if (type == typeof(Uri)) { return(JsonTypeDescription.Create(type, JsonObjectType.String, isNullable, JsonFormatStrings.Uri)); } if (type == typeof(byte)) { return(JsonTypeDescription.Create(type, JsonObjectType.Integer, false, JsonFormatStrings.Byte)); } if (type == typeof(byte[])) { return(JsonTypeDescription.Create(type, JsonObjectType.String, isNullable, JsonFormatStrings.Byte)); } if (type == typeof(JObject) || type == typeof(JToken) || type == typeof(object)) { return(JsonTypeDescription.Create(type, JsonObjectType.None, isNullable, null)); } if (IsFileType(type, parentAttributes)) { return(JsonTypeDescription.Create(type, JsonObjectType.File, isNullable, null)); } var contract = settings.ResolveContract(type); if (IsDictionaryType(type, parentAttributes) && contract is JsonDictionaryContract) { return(JsonTypeDescription.CreateForDictionary(type, JsonObjectType.Object, isNullable)); } if (IsArrayType(type, parentAttributes) && contract is JsonArrayContract) { return(JsonTypeDescription.Create(type, JsonObjectType.Array, isNullable, null)); } if (type.Name == "Nullable`1") { #if !LEGACY var typeDescription = GetDescription(type.GenericTypeArguments[0], parentAttributes, settings); #else var typeDescription = GetDescription(type.GetGenericArguments()[0], parentAttributes, settings); #endif typeDescription.IsNullable = true; return(typeDescription); } var jsonSchemaAttribute = type.GetTypeInfo().GetCustomAttribute <JsonSchemaAttribute>() ?? parentAttributes?.OfType <JsonSchemaAttribute>().SingleOrDefault(); if (jsonSchemaAttribute != null) { var classType = jsonSchemaAttribute.Type != JsonObjectType.None ? jsonSchemaAttribute.Type : JsonObjectType.Object; var format = !string.IsNullOrEmpty(jsonSchemaAttribute.Format) ? jsonSchemaAttribute.Format : null; return(JsonTypeDescription.Create(type, classType, isNullable, format)); } if (contract is JsonStringContract) { return(JsonTypeDescription.Create(type, JsonObjectType.String, isNullable, null)); } return(JsonTypeDescription.Create(type, JsonObjectType.Object, isNullable, null)); }