<PackageReference Include="NJsonSchema" Version="10.2.2" />

JsonSchema

A base class for describing a JSON schema.
using Namotion.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NJsonSchema.Collections; using NJsonSchema.Generation; using NJsonSchema.Infrastructure; using NJsonSchema.References; using NJsonSchema.Validation; using NJsonSchema.Validation.FormatValidators; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace NJsonSchema { [JsonConverter(typeof(ExtensionDataDeserializationConverter))] public class JsonSchema : JsonReferenceBase<JsonSchema>, IDocumentPathProvider, IJsonReference, IJsonReferenceBase, IJsonExtensionObject { internal static readonly HashSet<string> JsonSchemaPropertiesCache = new HashSet<string>((from p in ContextualTypeExtensions.GetContextualProperties(typeof(JsonSchema)) select p.get_Name()).ToArray()); private const SchemaType SerializationSchemaType = SchemaType.JsonSchema; private static Lazy<PropertyRenameAndIgnoreSerializerContractResolver> ContractResolver = new Lazy<PropertyRenameAndIgnoreSerializerContractResolver>(() => CreateJsonSerializerContractResolver(SchemaType.JsonSchema)); private IDictionary<string, JsonSchemaProperty> _properties; private IDictionary<string, JsonSchemaProperty> _patternProperties; private IDictionary<string, JsonSchema> _definitions; private ICollection<JsonSchema> _allOf; private ICollection<JsonSchema> _anyOf; private ICollection<JsonSchema> _oneOf; private JsonSchema _not; private JsonSchema _dictionaryKey; private JsonObjectType _type; private JsonSchema _item; private ICollection<JsonSchema> _items; private bool _allowAdditionalItems = true; private JsonSchema _additionalItemsSchema; private bool _allowAdditionalProperties = true; private JsonSchema _additionalPropertiesSchema; [JsonIgnore] private JsonXmlObject _xmlObject; private static JsonObjectType[] _jsonObjectTypeValues = (from v in Enum.GetValues(typeof(JsonObjectType)).OfType<JsonObjectType>() where v != JsonObjectType.None select v).ToArray(); private Lazy<object> _typeRaw; public static string ToolchainVersion => typeof(JsonSchema).GetTypeInfo().Assembly.GetName().Version + " (Newtonsoft.Json v" + typeof(JToken).GetTypeInfo().Assembly.GetName().Version + ")"; [JsonIgnore] public bool IsBinary { get { if (!Type.HasFlag(JsonObjectType.File)) { if (Type.HasFlag(JsonObjectType.String)) return Format == "binary"; return false; } return true; } } [JsonIgnore] public JsonSchema InheritedSchema { get { if (AllOf == null || AllOf.Count == 0 || HasReference) return null; if (AllOf.Count == 1) return AllOf.First().ActualSchema; if (AllOf.Any((JsonSchema s) => s.HasReference)) return AllOf.First((JsonSchema s) => s.HasReference).ActualSchema; if (AllOf.Any((JsonSchema s) => s.Type.HasFlag(JsonObjectType.Object))) return AllOf.First((JsonSchema s) => s.Type.HasFlag(JsonObjectType.Object)).ActualSchema; return AllOf.FirstOrDefault()?.ActualSchema; } } [JsonIgnore] public JsonSchema InheritedTypeSchema { get { if (ActualTypeSchema.IsDictionary || ActualTypeSchema.IsArray || ActualTypeSchema.IsTuple) return ActualTypeSchema; return InheritedSchema; } } [JsonIgnore] public IReadOnlyCollection<JsonSchema> AllInheritedSchemas { get { List<JsonSchema> list = (InheritedSchema != null) ? new List<JsonSchema> { InheritedSchema } : new List<JsonSchema>(); return list.Concat(list.SelectMany((JsonSchema s) => s.AllInheritedSchemas)).ToList(); } } [JsonIgnore] public OpenApiDiscriminator ResponsibleDiscriminatorObject { get { object openApiDiscriminator = ActualDiscriminatorObject; if (openApiDiscriminator == null) { JsonSchema inheritedSchema = InheritedSchema; if (inheritedSchema == null) return null; openApiDiscriminator = inheritedSchema.ActualSchema.ResponsibleDiscriminatorObject; } return (OpenApiDiscriminator)openApiDiscriminator; } } [JsonIgnore] public IReadOnlyDictionary<string, JsonSchemaProperty> ActualProperties { get { List<KeyValuePair<string, JsonSchemaProperty>> source = Properties.Union((from s in AllOf where s.ActualSchema != InheritedSchema select s).SelectMany((JsonSchema s) => s.ActualSchema.ActualProperties)).ToList(); List<IGrouping<string, KeyValuePair<string, JsonSchemaProperty>>> source2 = (from p in source group p by p.Key into g where g.Count() > 1 select g).ToList(); if (source2.Any()) throw new InvalidOperationException("The properties " + string.Join(", ", from g in source2 select "'" + g.Key + "'") + " are defined multiple times."); return new ReadOnlyDictionary<string, JsonSchemaProperty>(source.ToDictionary((KeyValuePair<string, JsonSchemaProperty> p) => p.Key, (KeyValuePair<string, JsonSchemaProperty> p) => p.Value)); } } [JsonProperty("$schema", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate, Order = -99)] public string SchemaVersion { get; set; } [JsonProperty("id", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate, Order = -98)] public string Id { get; set; } [JsonProperty("title", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate, Order = -97)] public string Title { get; set; } [JsonIgnore] public bool HasTypeNameTitle { get { if (!string.IsNullOrEmpty(Title)) return Regex.IsMatch(Title, "^[a-zA-Z0-9_]*$"); return false; } } [JsonProperty("description", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public virtual string Description { get; set; } [JsonIgnore] public JsonObjectType Type { get { return _type; } set { _type = value; ResetTypeRaw(); } } [JsonIgnore] public JsonSchema ParentSchema { get { return Parent as JsonSchema; } } [JsonIgnore] public virtual object Parent { get; set; } [JsonProperty("format", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public string Format { get; set; } [JsonProperty("default", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public object Default { get; set; } [JsonProperty("multipleOf", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public decimal? MultipleOf { get; set; } [JsonProperty("maximum", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public decimal? Maximum { get; set; } [JsonIgnore] public decimal? ExclusiveMaximum { get; set; } [JsonIgnore] public bool IsExclusiveMaximum { get; set; } [JsonProperty("minimum", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public decimal? Minimum { get; set; } [JsonIgnore] public decimal? ExclusiveMinimum { get; set; } [JsonIgnore] public bool IsExclusiveMinimum { get; set; } [JsonProperty("maxLength", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public int? MaxLength { get; set; } [JsonProperty("minLength", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public int? MinLength { get; set; } [JsonProperty("pattern", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public string Pattern { get; set; } [JsonProperty("maxItems", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public int MaxItems { get; set; } [JsonProperty("minItems", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public int MinItems { get; set; } [JsonProperty("uniqueItems", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public bool UniqueItems { get; set; } [JsonProperty("maxProperties", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public int MaxProperties { get; set; } [JsonProperty("minProperties", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public int MinProperties { get; set; } [JsonProperty("x-deprecated", DefaultValueHandling = DefaultValueHandling.Ignore)] public bool IsDeprecated { get; set; } [JsonProperty("x-deprecatedMessage", DefaultValueHandling = DefaultValueHandling.Ignore)] public string DeprecatedMessage { get; set; } [JsonProperty("x-abstract", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public bool IsAbstract { get; set; } [JsonProperty("x-nullable", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public bool? IsNullableRaw { get; set; } [JsonProperty("x-example", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public object Example { get; set; } [JsonProperty("x-enumFlags", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public bool IsFlagEnumerable { get; set; } [JsonIgnore] public ICollection<object> Enumeration { get; set; } [JsonIgnore] public bool IsEnumeration { get { return Enumeration.Count > 0; } } [JsonIgnore] public ICollection<string> RequiredProperties { get; set; } [JsonProperty("x-dictionaryKey", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public JsonSchema DictionaryKey { get { return _dictionaryKey; } set { _dictionaryKey = value; if (_dictionaryKey != null) _dictionaryKey.Parent = this; } } [JsonIgnore] public IDictionary<string, JsonSchemaProperty> Properties { get { return _properties; } internal set { if (_properties != value) { RegisterProperties(_properties, value); _properties = value; } } } [JsonProperty("xml", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public JsonXmlObject Xml { get { return _xmlObject; } set { _xmlObject = value; if (_xmlObject != null) _xmlObject.ParentSchema = this; } } [JsonIgnore] public IDictionary<string, JsonSchemaProperty> PatternProperties { get { return _patternProperties; } internal set { if (_patternProperties != value) { RegisterSchemaDictionary(_patternProperties, value); _patternProperties = value; } } } [JsonIgnore] public JsonSchema Item { get { return _item; } set { if (_item != value) { _item = value; if (_item != null) { _item.Parent = this; Items.Clear(); } } } } [JsonIgnore] public ICollection<JsonSchema> Items { get { return _items; } internal set { if (_items != value) { RegisterSchemaCollection(_items, value); _items = value; if (_items != null) Item = null; } } } [JsonProperty("not", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public JsonSchema Not { get { return _not; } set { _not = value; if (_not != null) _not.Parent = this; } } [JsonIgnore] public IDictionary<string, JsonSchema> Definitions { get { return _definitions; } internal set { if (_definitions != value) { RegisterSchemaDictionary(_definitions, value); _definitions = value; } } } [JsonIgnore] public ICollection<JsonSchema> AllOf { get { return _allOf; } internal set { if (_allOf != value) { RegisterSchemaCollection(_allOf, value); _allOf = value; } } } [JsonIgnore] public ICollection<JsonSchema> AnyOf { get { return _anyOf; } internal set { if (_anyOf != value) { RegisterSchemaCollection(_anyOf, value); _anyOf = value; } } } [JsonIgnore] public ICollection<JsonSchema> OneOf { get { return _oneOf; } internal set { if (_oneOf != value) { RegisterSchemaCollection(_oneOf, value); _oneOf = value; } } } [JsonIgnore] public bool AllowAdditionalItems { get { return _allowAdditionalItems; } set { if (_allowAdditionalItems != value) { _allowAdditionalItems = value; if (!_allowAdditionalItems) AdditionalItemsSchema = null; } } } [JsonIgnore] public JsonSchema AdditionalItemsSchema { get { return _additionalItemsSchema; } set { if (_additionalItemsSchema != value) { _additionalItemsSchema = value; if (_additionalItemsSchema != null) AllowAdditionalItems = true; } } } [JsonIgnore] public bool AllowAdditionalProperties { get { return _allowAdditionalProperties; } set { if (_allowAdditionalProperties != value) { _allowAdditionalProperties = value; if (!_allowAdditionalProperties) AdditionalPropertiesSchema = null; } } } [JsonIgnore] public JsonSchema AdditionalPropertiesSchema { get { return _additionalPropertiesSchema; } set { if (_additionalPropertiesSchema != value) { _additionalPropertiesSchema = value; if (_additionalPropertiesSchema != null) AllowAdditionalProperties = true; } } } [JsonIgnore] public bool IsObject { get { return Type.HasFlag(JsonObjectType.Object); } } [JsonIgnore] public bool IsArray { get { if (Type.HasFlag(JsonObjectType.Array)) { if (Items != null) return Items.Count == 0; return true; } return false; } } [JsonIgnore] public bool IsTuple { get { if (Type.HasFlag(JsonObjectType.Array)) { ICollection<JsonSchema> items = Items; if (items == null) return false; return items.Any(); } return false; } } [JsonIgnore] public bool IsDictionary { get { if (Type.HasFlag(JsonObjectType.Object) && ActualProperties.Count == 0) { if (AdditionalPropertiesSchema == null) return PatternProperties.Any(); return true; } return false; } } [JsonIgnore] public bool IsAnyType { get { if ((Type.HasFlag(JsonObjectType.Object) || Type == JsonObjectType.None) && Reference == null && AllOf.Count == 0 && AnyOf.Count == 0 && OneOf.Count == 0 && ActualProperties.Count == 0 && PatternProperties.Count == 0 && AdditionalPropertiesSchema == null && !MultipleOf.HasValue) return !IsEnumeration; return false; } } [JsonIgnore] public virtual JsonSchema ActualSchema { get { return GetActualSchema(new List<JsonSchema>()); } } [JsonIgnore] public virtual JsonSchema ActualTypeSchema { get { JsonSchema jsonSchema = (Reference != null) ? Reference : this; if (jsonSchema.AllOf.Count > 1 && jsonSchema.AllOf.Count(delegate(JsonSchema s) { if (!s.HasReference) return !s.IsDictionary; return false; }) == 1) return jsonSchema.AllOf.First(delegate(JsonSchema s) { if (!s.HasReference) return !s.IsDictionary; return false; }).ActualSchema; return jsonSchema.OneOf.FirstOrDefault((JsonSchema o) => !o.IsNullable(SchemaType.JsonSchema))?.ActualSchema ?? ActualSchema; } } [JsonIgnore] public bool HasReference { get { if (Reference == null && !HasAllOfSchemaReference && !HasOneOfSchemaReference) return HasAnyOfSchemaReference; return true; } } [JsonIgnore] public bool HasAllOfSchemaReference { get { if (AllOf.Count == 1 && AllOf.Any((JsonSchema s) => s.HasReference) && Type == JsonObjectType.None && AnyOf.Count == 0 && OneOf.Count == 0 && Properties.Count == 0 && PatternProperties.Count == 0 && AdditionalPropertiesSchema == null && !MultipleOf.HasValue) return !IsEnumeration; return false; } } [JsonIgnore] public bool HasOneOfSchemaReference { get { if (OneOf.Count == 1 && OneOf.Any((JsonSchema s) => s.HasReference) && Type == JsonObjectType.None && AnyOf.Count == 0 && AllOf.Count == 0 && Properties.Count == 0 && PatternProperties.Count == 0 && AdditionalPropertiesSchema == null && !MultipleOf.HasValue) return !IsEnumeration; return false; } } [JsonIgnore] public bool HasAnyOfSchemaReference { get { if (AnyOf.Count == 1 && AnyOf.Any((JsonSchema s) => s.HasReference) && Type == JsonObjectType.None && AllOf.Count == 0 && OneOf.Count == 0 && Properties.Count == 0 && PatternProperties.Count == 0 && AdditionalPropertiesSchema == null && !MultipleOf.HasValue) return !IsEnumeration; return false; } } [JsonIgnore] IJsonReference IJsonReference.ActualObject { get { return ActualSchema; } } [JsonIgnore] object IJsonReference.PossibleRoot { get { return Parent; } } [JsonIgnore] public override JsonSchema Reference { get { return base.Reference; } set { base.Reference = value; if (value != null) Type = JsonObjectType.None; } } [JsonExtensionData] public IDictionary<string, object> ExtensionData { get; set; } [JsonIgnore] public string ActualDiscriminator { get { return ActualTypeSchema.Discriminator; } } [JsonIgnore] public string Discriminator { get { return DiscriminatorObject?.PropertyName; } set { if (!string.IsNullOrEmpty(value)) DiscriminatorObject = new OpenApiDiscriminator { PropertyName = value }; else DiscriminatorObject = null; } } [JsonIgnore] public OpenApiDiscriminator ActualDiscriminatorObject { get { return DiscriminatorObject ?? ActualTypeSchema.DiscriminatorObject; } } [JsonIgnore] public OpenApiDiscriminator DiscriminatorObject { get; set; } [JsonProperty("discriminator", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate, Order = -95)] internal object DiscriminatorRaw { get { if (JsonSchemaSerialization.CurrentSchemaType != SchemaType.Swagger2) return DiscriminatorObject; return Discriminator; } set { if (value is string) Discriminator = (string)value; else if (value != null) { DiscriminatorObject = ((JObject)value).ToObject<OpenApiDiscriminator>(); } } } [JsonIgnore] public Collection<string> EnumerationNames { get; set; } [JsonProperty("exclusiveMaximum", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal object ExclusiveMaximumRaw { get { decimal? exclusiveMaximum = ExclusiveMaximum; if (!exclusiveMaximum.HasValue) { if (!IsExclusiveMaximum) return null; return true; } return exclusiveMaximum.GetValueOrDefault(); } set { if (value is bool) IsExclusiveMaximum = (bool)value; else if (value != null && (value.Equals("true") || value.Equals("false"))) { IsExclusiveMaximum = value.Equals("true"); } else if (value != null) { ExclusiveMaximum = Convert.ToDecimal(value); } } } [JsonProperty("exclusiveMinimum", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal object ExclusiveMinimumRaw { get { decimal? exclusiveMinimum = ExclusiveMinimum; if (!exclusiveMinimum.HasValue) { if (!IsExclusiveMinimum) return null; return true; } return exclusiveMinimum.GetValueOrDefault(); } set { if (value is bool) IsExclusiveMinimum = (bool)value; else if (value != null && (value.Equals("true") || value.Equals("false"))) { IsExclusiveMinimum = value.Equals("true"); } else if (value != null) { ExclusiveMinimum = Convert.ToDecimal(value); } } } [JsonProperty("additionalItems", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal object AdditionalItemsRaw { get { if (AdditionalItemsSchema != null) return AdditionalItemsSchema; if (!AllowAdditionalItems) return false; return null; } set { if (value is bool) AllowAdditionalItems = (bool)value; else if (value != null && (value.Equals("true") || value.Equals("false"))) { AllowAdditionalItems = value.Equals("true"); } else if (value != null) { AdditionalItemsSchema = FromJsonWithCurrentSettings(value); } } } [JsonProperty("additionalProperties", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal object AdditionalPropertiesRaw { get { if (AdditionalPropertiesSchema != null) return AdditionalPropertiesSchema; if (JsonSchemaSerialization.CurrentSchemaType == SchemaType.Swagger2) { if (AllowAdditionalProperties && (Type.HasFlag(JsonObjectType.Object) || Type == JsonObjectType.None) && !HasReference && !AllOf.Any() && !TypeExtensions.IsAssignableToTypeName(GetType(), "OpenApiParameter", 0)) return new JObject(); return null; } if (!AllowAdditionalProperties) return false; return null; } set { if (value is bool) AllowAdditionalProperties = (bool)value; else if (value != null && (value.Equals("true") || value.Equals("false"))) { AllowAdditionalProperties = value.Equals("true"); } else if (value != null) { AdditionalPropertiesSchema = FromJsonWithCurrentSettings(value); } } } [JsonProperty("items", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal object ItemsRaw { get { if (Item != null) return Item; if (Items.Count > 0) return Items; return null; } set { if (value is JArray) Items = new ObservableCollection<JsonSchema>(from t in (JArray)value select FromJsonWithCurrentSettings(t)); else if (value != null) { Item = FromJsonWithCurrentSettings(value); } } } [JsonProperty("type", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate, Order = -97)] internal object TypeRaw { get { if (_typeRaw == null) ResetTypeRaw(); return _typeRaw.Value; } set { if (value is JArray) Type = ((JArray)value).Aggregate(JsonObjectType.None, (JsonObjectType type, JToken token) => type | ConvertStringToJsonObjectType(token.ToString())); else Type = ConvertStringToJsonObjectType(value as string); ResetTypeRaw(); } } [JsonProperty("required", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal ICollection<string> RequiredPropertiesRaw { get { if (RequiredProperties == null || RequiredProperties.Count <= 0) return null; return RequiredProperties; } set { RequiredProperties = value; } } [JsonProperty("properties", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal IDictionary<string, JsonSchemaProperty> PropertiesRaw { get { if (Properties == null || Properties.Count <= 0) return null; return Properties; } set { Properties = ((value != null) ? new ObservableDictionary<string, JsonSchemaProperty>(value) : new ObservableDictionary<string, JsonSchemaProperty>()); } } [JsonProperty("patternProperties", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal IDictionary<string, JsonSchemaProperty> PatternPropertiesRaw { get { if (PatternProperties == null || PatternProperties.Count <= 0) return null; return PatternProperties.ToDictionary((KeyValuePair<string, JsonSchemaProperty> p) => p.Key, (KeyValuePair<string, JsonSchemaProperty> p) => p.Value); } set { PatternProperties = ((value != null) ? new ObservableDictionary<string, JsonSchemaProperty>(value) : new ObservableDictionary<string, JsonSchemaProperty>()); } } [JsonProperty("definitions", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal IDictionary<string, JsonSchema> DefinitionsRaw { get { if (Definitions == null || Definitions.Count <= 0) return null; return Definitions; } set { Definitions = ((value != null) ? new ObservableDictionary<string, JsonSchema>(value) : new ObservableDictionary<string, JsonSchema>()); } } [JsonProperty("x-enumNames", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal Collection<string> EnumerationNamesRaw { get { if (EnumerationNames == null || EnumerationNames.Count <= 0) return null; return EnumerationNames; } set { EnumerationNames = ((value != null) ? new ObservableCollection<string>(value) : new ObservableCollection<string>()); } } [JsonProperty("enum", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal ICollection<object> EnumerationRaw { get { if (Enumeration == null || Enumeration.Count <= 0) return null; return Enumeration; } set { Enumeration = ((value != null) ? new ObservableCollection<object>(value) : new ObservableCollection<object>()); } } [JsonProperty("allOf", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal ICollection<JsonSchema> AllOfRaw { get { if (AllOf == null || AllOf.Count <= 0) return null; return AllOf; } set { AllOf = ((value != null) ? new ObservableCollection<JsonSchema>(value) : new ObservableCollection<JsonSchema>()); } } [JsonProperty("anyOf", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal ICollection<JsonSchema> AnyOfRaw { get { if (AnyOf == null || AnyOf.Count <= 0) return null; return AnyOf; } set { AnyOf = ((value != null) ? new ObservableCollection<JsonSchema>(value) : new ObservableCollection<JsonSchema>()); } } [JsonProperty("oneOf", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] internal ICollection<JsonSchema> OneOfRaw { get { if (OneOf == null || OneOf.Count <= 0) return null; return OneOf; } set { OneOf = ((value != null) ? new ObservableCollection<JsonSchema>(value) : new ObservableCollection<JsonSchema>()); } } public JsonSchema() { Initialize(); if (JsonSchemaSerialization.CurrentSchemaType == SchemaType.Swagger2) _allowAdditionalProperties = false; } public static JsonSchema CreateAnySchema() { return new JsonSchema(); } public static TSchemaType CreateAnySchema<TSchemaType>() where TSchemaType : JsonSchema, new { return new TSchemaType(); } public static JsonSchema FromType<TType>() { return FromType<TType>(new JsonSchemaGeneratorSettings()); } public static JsonSchema FromType(Type type) { return FromType(type, new JsonSchemaGeneratorSettings()); } public static JsonSchema FromType<TType>(JsonSchemaGeneratorSettings settings) { return new JsonSchemaGenerator(settings).Generate(typeof(TType)); } public static JsonSchema FromType(Type type, JsonSchemaGeneratorSettings settings) { return new JsonSchemaGenerator(settings).Generate(type); } public static JsonSchema FromSampleJson(string data) { return new SampleJsonSchemaGenerator().Generate(data); } public static async Task<JsonSchema> FromFileAsync(string filePath) { Func<JsonSchema, JsonReferenceResolver> referenceResolverFactory = JsonReferenceResolver.CreateJsonReferenceResolverFactory(new DefaultTypeNameGenerator()); return await FromFileAsync(filePath, referenceResolverFactory).ConfigureAwait(false); } public static async Task<JsonSchema> FromFileAsync(string filePath, Func<JsonSchema, JsonReferenceResolver> referenceResolverFactory) { return await FromJsonAsync(DynamicApis.FileReadAllText(filePath), filePath, referenceResolverFactory).ConfigureAwait(false); } public static async Task<JsonSchema> FromUrlAsync(string url) { Func<JsonSchema, JsonReferenceResolver> referenceResolverFactory = JsonReferenceResolver.CreateJsonReferenceResolverFactory(new DefaultTypeNameGenerator()); return await FromUrlAsync(url, referenceResolverFactory).ConfigureAwait(false); } public static async Task<JsonSchema> FromUrlAsync(string url, Func<JsonSchema, JsonReferenceResolver> referenceResolverFactory) { return await FromJsonAsync(await DynamicApis.HttpGetAsync(url).ConfigureAwait(false), url, referenceResolverFactory).ConfigureAwait(false); } public static async Task<JsonSchema> FromJsonAsync(string data) { return await FromJsonAsync(data, null).ConfigureAwait(false); } public static async Task<JsonSchema> FromJsonAsync(string data, string documentPath) { Func<JsonSchema, JsonReferenceResolver> referenceResolverFactory = JsonReferenceResolver.CreateJsonReferenceResolverFactory(new DefaultTypeNameGenerator()); return await FromJsonAsync(data, documentPath, referenceResolverFactory).ConfigureAwait(false); } public static async Task<JsonSchema> FromJsonAsync(string data, string documentPath, Func<JsonSchema, JsonReferenceResolver> referenceResolverFactory) { return await JsonSchemaSerialization.FromJsonAsync(data, SchemaType.JsonSchema, documentPath, referenceResolverFactory, ContractResolver.Value).ConfigureAwait(false); } internal static JsonSchema FromJsonWithCurrentSettings(object obj) { return JsonConvert.DeserializeObject<JsonSchema>(JsonConvert.SerializeObject(obj, JsonSchemaSerialization.CurrentSerializerSettings), JsonSchemaSerialization.CurrentSerializerSettings); } public bool Inherits(JsonSchema schema) { schema = schema.ActualSchema; if (InheritedSchema?.ActualSchema != schema) return InheritedSchema?.Inherits(schema) ?? false; return true; } public virtual bool IsNullable(SchemaType schemaType) { bool? isNullableRaw = IsNullableRaw; bool flag = true; if ((isNullableRaw.GetValueOrDefault() == flag) & isNullableRaw.HasValue) return true; if (IsEnumeration && Enumeration.Contains(null)) return true; if (Type.HasFlag(JsonObjectType.Null)) return true; if ((Type == JsonObjectType.None || Type.HasFlag(JsonObjectType.Null)) && OneOf.Any((JsonSchema o) => o.IsNullable(schemaType))) return true; if (ActualSchema != this && ActualSchema.IsNullable(schemaType)) return true; if (ActualTypeSchema != this && ActualTypeSchema.IsNullable(schemaType)) return true; return false; } public string ToJson() { return ToJson(Formatting.Indented); } public string ToJson(Formatting formatting) { string schemaVersion = SchemaVersion; SchemaVersion = "http://json-schema.org/draft-04/schema#"; string result = JsonSchemaSerialization.ToJson(this, SchemaType.JsonSchema, ContractResolver.Value, formatting); SchemaVersion = schemaVersion; return result; } public JToken ToSampleJson() { return new SampleJsonDataGenerator().Generate(this); } public bool InheritsSchema(JsonSchema parentSchema) { if (parentSchema != null) return ActualSchema.AllInheritedSchemas.Concat(new List<JsonSchema> { this }).Any((JsonSchema s) => s.ActualSchema == parentSchema.ActualSchema); return false; } public ICollection<ValidationError> Validate(string jsonData, params IFormatValidator[] customValidators) { return new JsonSchemaValidator(customValidators).Validate(jsonData, ActualSchema); } public ICollection<ValidationError> Validate(JToken token, params IFormatValidator[] customValidators) { return new JsonSchemaValidator(customValidators).Validate(token, ActualSchema); } private static JsonObjectType ConvertStringToJsonObjectType(string value) { if (value != null) { switch (value) { case "array": return JsonObjectType.Array; case "boolean": return JsonObjectType.Boolean; case "integer": return JsonObjectType.Integer; case "number": return JsonObjectType.Number; case "null": return JsonObjectType.Null; case "object": return JsonObjectType.Object; case "string": return JsonObjectType.String; case "file": return JsonObjectType.File; } } return JsonObjectType.None; } private void Initialize() { if (Items == null) Items = new ObservableCollection<JsonSchema>(); if (Properties == null) Properties = new ObservableDictionary<string, JsonSchemaProperty>(); if (PatternProperties == null) PatternProperties = new ObservableDictionary<string, JsonSchemaProperty>(); if (Definitions == null) Definitions = new ObservableDictionary<string, JsonSchema>(); if (RequiredProperties == null) RequiredProperties = new ObservableCollection<string>(); if (AllOf == null) AllOf = new ObservableCollection<JsonSchema>(); if (AnyOf == null) AnyOf = new ObservableCollection<JsonSchema>(); if (OneOf == null) OneOf = new ObservableCollection<JsonSchema>(); if (Enumeration == null) Enumeration = new Collection<object>(); if (EnumerationNames == null) EnumerationNames = new Collection<string>(); } private JsonSchema GetActualSchema(IList<JsonSchema> checkedSchemas) { if (checkedSchemas.Contains(this)) throw new InvalidOperationException("Cyclic references detected."); if (((IJsonReferenceBase)this).ReferencePath != null && Reference == null) throw new InvalidOperationException("The schema reference path '" + ((IJsonReferenceBase)this).ReferencePath + "' has not been resolved."); if (HasReference) { checkedSchemas.Add(this); if (HasAllOfSchemaReference) return AllOf.First().GetActualSchema(checkedSchemas); if (HasOneOfSchemaReference) return OneOf.First().GetActualSchema(checkedSchemas); if (HasAnyOfSchemaReference) return AnyOf.First().GetActualSchema(checkedSchemas); return Reference.GetActualSchema(checkedSchemas); } return this; } public static PropertyRenameAndIgnoreSerializerContractResolver CreateJsonSerializerContractResolver(SchemaType schemaType) { IgnoreEmptyCollectionsContractResolver ignoreEmptyCollectionsContractResolver = new IgnoreEmptyCollectionsContractResolver(); switch (schemaType) { case SchemaType.OpenApi3: ignoreEmptyCollectionsContractResolver.RenameProperty(typeof(JsonSchemaProperty), "x-readOnly", "readOnly"); ignoreEmptyCollectionsContractResolver.RenameProperty(typeof(JsonSchemaProperty), "x-writeOnly", "writeOnly"); ignoreEmptyCollectionsContractResolver.RenameProperty(typeof(JsonSchema), "x-nullable", "nullable"); ignoreEmptyCollectionsContractResolver.RenameProperty(typeof(JsonSchema), "x-example", "example"); ignoreEmptyCollectionsContractResolver.RenameProperty(typeof(JsonSchema), "x-deprecated", "deprecated"); break; case SchemaType.Swagger2: ignoreEmptyCollectionsContractResolver.RenameProperty(typeof(JsonSchemaProperty), "x-readOnly", "readOnly"); ignoreEmptyCollectionsContractResolver.RenameProperty(typeof(JsonSchema), "x-example", "example"); break; default: ignoreEmptyCollectionsContractResolver.RenameProperty(typeof(JsonSchemaProperty), "x-readOnly", "readonly"); break; } return ignoreEmptyCollectionsContractResolver; } [OnDeserialized] internal void OnDeserialized(StreamingContext ctx) { Initialize(); } private void ResetTypeRaw() { _typeRaw = new Lazy<object>(delegate { JsonObjectType[] array = (from v in _jsonObjectTypeValues where Type.HasFlag(v) select v).ToArray(); if (array.Length > 1) return new JArray(from f in array select new JValue(f.ToString().ToLowerInvariant())); if (array.Length == 1) return new JValue(array[0].ToString().ToLowerInvariant()); return null; }); } private void RegisterProperties(IDictionary<string, JsonSchemaProperty> oldCollection, IDictionary<string, JsonSchemaProperty> newCollection) { if (oldCollection != null) ((ObservableDictionary<string, JsonSchemaProperty>)oldCollection).CollectionChanged -= InitializeSchemaCollection; if (newCollection != null) { ((ObservableDictionary<string, JsonSchemaProperty>)newCollection).CollectionChanged += InitializeSchemaCollection; InitializeSchemaCollection(newCollection, null); } } private void RegisterSchemaDictionary<T>(IDictionary<string, T> oldCollection, IDictionary<string, T> newCollection) where T : JsonSchema { if (oldCollection != null) ((ObservableDictionary<string, T>)oldCollection).CollectionChanged -= InitializeSchemaCollection; if (newCollection != null) { ((ObservableDictionary<string, T>)newCollection).CollectionChanged += InitializeSchemaCollection; InitializeSchemaCollection(newCollection, null); } } private void RegisterSchemaCollection(ICollection<JsonSchema> oldCollection, ICollection<JsonSchema> newCollection) { if (oldCollection != null) ((ObservableCollection<JsonSchema>)oldCollection).CollectionChanged -= InitializeSchemaCollection; if (newCollection != null) { ((ObservableCollection<JsonSchema>)newCollection).CollectionChanged += InitializeSchemaCollection; InitializeSchemaCollection(newCollection, null); } } private void InitializeSchemaCollection(object sender, NotifyCollectionChangedEventArgs e) { if (sender is ObservableDictionary<string, JsonSchemaProperty>) { foreach (KeyValuePair<string, JsonSchemaProperty> item in (ObservableDictionary<string, JsonSchemaProperty>)sender) { item.Value.Name = item.Key; item.Value.Parent = this; } } else if (sender is ObservableCollection<JsonSchema>) { foreach (JsonSchema item2 in (ObservableCollection<JsonSchema>)sender) { item2.Parent = this; } } else if (sender is ObservableDictionary<string, JsonSchema>) { ObservableDictionary<string, JsonSchema> observableDictionary = (ObservableDictionary<string, JsonSchema>)sender; KeyValuePair<string, JsonSchema>[] array = observableDictionary.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair<string, JsonSchema> keyValuePair = array[i]; if (keyValuePair.Value == null) observableDictionary.Remove(keyValuePair.Key); else keyValuePair.Value.Parent = this; } } } } }