JsonSchema
public class JsonSchema : JsonReferenceBase<JsonSchema>, IDocumentPathProvider, IJsonReference, IJsonReferenceBase, IJsonExtensionObject
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;
}
}
}
}
}