private void Push(JsonSchema value) { _currentSchema = value; _stack.Add(value); _resolver.LoadedSchemas.Add(value); _documentSchemas.Add(value.Location, value); }
public void AddRequiredWithOneValueWhenPropertyDoesntExist() { JsonSchema jsonSchema = new JsonSchema(); Assert.Throws<ArgumentException>(() => { jsonSchema.AddRequired("a"); }); Assert.Null(jsonSchema.Properties); Assert.Null(jsonSchema.Required); }
private JsonSchema Pop() { JsonSchema poppedSchema = _currentSchema; _stack.RemoveAt(_stack.Count - 1); _currentSchema = _stack.LastOrDefault(); return poppedSchema; }
public void TestJsonSchema() { var schema = new JsonSchema(); TestJsonSchemaCommon(schema); // Json should not accept plain literal Assert.AreEqual(null, schema.GetDefaultTag(new Scalar(null, null, "boom", ScalarStyle.Plain, true, false))); }
public TypeSchema(Type type, JsonSchema schema) { ValidationUtils.ArgumentNotNull(type, "type"); ValidationUtils.ArgumentNotNull(schema, "schema"); Type = type; Schema = schema; }
public JsonSchemaNode(JsonSchema schema) { Schemas = new ReadOnlyCollection<JsonSchema>(new[] { schema }); Properties = new Dictionary<string, JsonSchemaNode>(); PatternProperties = new Dictionary<string, JsonSchemaNode>(); Items = new List<JsonSchemaNode>(); Id = GetId(Schemas); }
/// <summary> /// Determines whether the <see cref="JToken"/> is valid. /// </summary> /// <param name="source">The source <see cref="JToken"/> to test.</param> /// <param name="schema">The schema to test with.</param> /// <param name="errorMessages">When this method returns, contains any error messages generated while validating. </param> /// <returns> /// <c>true</c> if the specified <see cref="JToken"/> is valid; otherwise, <c>false</c>. /// </returns> public static bool IsValid(this JToken source, JsonSchema schema, out IList<string> errorMessages) { IList<string> errors = new List<string>(); source.Validate(schema, (sender, args) => errors.Add(args.Message)); errorMessages = errors; return (errorMessages.Count == 0); }
public JsonSchemaModel Build(JsonSchema schema) { _nodes = new JsonSchemaNodeCollection(); _node = AddSchema(null, schema); _nodeModels = new Dictionary<JsonSchemaNode, JsonSchemaModel>(); JsonSchemaModel model = BuildNodeModel(_node); return model; }
private JsonSchemaNode(JsonSchemaNode source, JsonSchema schema) { Schemas = new ReadOnlyCollection<JsonSchema>(source.Schemas.Union(new[] { schema }).ToList()); Properties = new Dictionary<string, JsonSchemaNode>(source.Properties); PatternProperties = new Dictionary<string, JsonSchemaNode>(source.PatternProperties); Items = new List<JsonSchemaNode>(source.Items); AdditionalProperties = source.AdditionalProperties; AdditionalItems = source.AdditionalItems; Id = GetId(Schemas); }
public void AddRequiredWithThreeValuesWhenAllPropertiesExist() { JsonSchema jsonSchema = new JsonSchema(); jsonSchema.AddProperty("a", new JsonSchema()); jsonSchema.AddProperty("b", new JsonSchema()); jsonSchema.AddProperty("c", new JsonSchema()); jsonSchema.AddRequired("a", "b", "c"); Assert.Equal(new List<string>() { "a", "b", "c" }, jsonSchema.Required); }
public JsonSchemaNode AddSchema(JsonSchemaNode existingNode, JsonSchema schema) { string newId; if (existingNode != null) { if (existingNode.Schemas.Contains(schema)) return existingNode; newId = JsonSchemaNode.GetId(existingNode.Schemas.Union(new[] { schema })); } else { newId = JsonSchemaNode.GetId(new[] { schema }); } if (_nodes.Contains(newId)) return _nodes[newId]; JsonSchemaNode currentNode = (existingNode != null) ? existingNode.Combine(schema) : new JsonSchemaNode(schema); _nodes.Add(currentNode); AddProperties(schema.Properties, currentNode.Properties); AddProperties(schema.PatternProperties, currentNode.PatternProperties); if (schema.Items != null) { for (int i = 0; i < schema.Items.Count; i++) { AddItem(currentNode, i, schema.Items[i]); } } if (schema.AdditionalItems != null) AddAdditionalItems(currentNode, schema.AdditionalItems); if (schema.AdditionalProperties != null) AddAdditionalProperties(currentNode, schema.AdditionalProperties); if (schema.Extends != null) { foreach (JsonSchema jsonSchema in schema.Extends) { currentNode = AddSchema(currentNode, jsonSchema); } } return currentNode; }
private void ReferenceOrWriteSchema(JsonSchema schema) { if (schema.Id != null && _resolver.GetSchema(schema.Id) != null) { _writer.WriteStartObject(); _writer.WritePropertyName(JsonTypeReflector.RefPropertyName); _writer.WriteValue(schema.Id); _writer.WriteEndObject(); } else { WriteSchema(schema); } }
private static void Combine(JsonSchemaModel model, JsonSchema schema) { // Version 3 of the Draft JSON Schema has the default value of Not Required model.Required = model.Required || (schema.Required ?? false); model.Type = model.Type & (schema.Type ?? JsonSchemaType.Any); model.MinimumLength = MathUtils.Max(model.MinimumLength, schema.MinimumLength); model.MaximumLength = MathUtils.Min(model.MaximumLength, schema.MaximumLength); // not sure what is the best way to combine divisibleBy model.DivisibleBy = MathUtils.Max(model.DivisibleBy, schema.DivisibleBy); model.Minimum = MathUtils.Max(model.Minimum, schema.Minimum); model.Maximum = MathUtils.Max(model.Maximum, schema.Maximum); model.ExclusiveMinimum = model.ExclusiveMinimum || (schema.ExclusiveMinimum ?? false); model.ExclusiveMaximum = model.ExclusiveMaximum || (schema.ExclusiveMaximum ?? false); model.MinimumItems = MathUtils.Max(model.MinimumItems, schema.MinimumItems); model.MaximumItems = MathUtils.Min(model.MaximumItems, schema.MaximumItems); model.PositionalItemsValidation = model.PositionalItemsValidation || schema.PositionalItemsValidation; model.AllowAdditionalProperties = model.AllowAdditionalProperties && schema.AllowAdditionalProperties; model.AllowAdditionalItems = model.AllowAdditionalItems && schema.AllowAdditionalItems; model.UniqueItems = model.UniqueItems || schema.UniqueItems; if (schema.Enum != null) { if (model.Enum == null) model.Enum = new List<JToken>(); model.Enum.AddRangeDistinct(schema.Enum, JToken.EqualityComparer); } model.Disallow = model.Disallow | (schema.Disallow ?? JsonSchemaType.None); if (schema.Pattern != null) { if (model.Patterns == null) model.Patterns = new List<string>(); model.Patterns.AddDistinct(schema.Pattern); } }
public static JsonSchemaProperty ObjectProperty(JsonSchema reference, string?description = null, bool isRequired = false) { return(Enrich(new JsonSchemaProperty { Reference = reference }, description, isRequired)); }
public void GenerateSchemaForDirectoryInfo() { JsonSchemaGenerator generator = new JsonSchemaGenerator(); generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName; generator.ContractResolver = new CustomDirectoryInfoMapper { #if !(NETFX_CORE || PORTABLE || ASPNETCORE50) IgnoreSerializableAttribute = true #endif }; JsonSchema schema = generator.Generate(typeof(DirectoryInfo), true); string json = schema.ToString(); StringAssert.AreEqual(@"{ ""id"": ""System.IO.DirectoryInfo"", ""required"": true, ""type"": [ ""object"", ""null"" ], ""additionalProperties"": false, ""properties"": { ""Name"": { ""required"": true, ""type"": [ ""string"", ""null"" ] }, ""Parent"": { ""$ref"": ""System.IO.DirectoryInfo"" }, ""Exists"": { ""required"": true, ""type"": ""boolean"" }, ""FullName"": { ""required"": true, ""type"": [ ""string"", ""null"" ] }, ""Extension"": { ""required"": true, ""type"": [ ""string"", ""null"" ] }, ""CreationTime"": { ""required"": true, ""type"": ""string"" }, ""CreationTimeUtc"": { ""required"": true, ""type"": ""string"" }, ""LastAccessTime"": { ""required"": true, ""type"": ""string"" }, ""LastAccessTimeUtc"": { ""required"": true, ""type"": ""string"" }, ""LastWriteTime"": { ""required"": true, ""type"": ""string"" }, ""LastWriteTimeUtc"": { ""required"": true, ""type"": ""string"" }, ""Attributes"": { ""required"": true, ""type"": ""integer"" } } }", json); DirectoryInfo temp = new DirectoryInfo(@"c:\temp"); JTokenWriter jsonWriter = new JTokenWriter(); JsonSerializer serializer = new JsonSerializer(); serializer.Converters.Add(new IsoDateTimeConverter()); serializer.ContractResolver = new CustomDirectoryInfoMapper { #if !(NETFX_CORE || PORTABLE || ASPNETCORE50) IgnoreSerializableInterface = true #endif }; serializer.Serialize(jsonWriter, temp); List <string> errors = new List <string>(); jsonWriter.Token.Validate(schema, (sender, args) => errors.Add(args.Message)); Assert.AreEqual(0, errors.Count); }
public string Generate(JsonSchema schema, string typeNameHint) => typeNameHint;
/// <summary>Resolves and possibly generates the specified schema.</summary> /// <param name="schema">The schema.</param> /// <param name="isNullable">Specifies whether the given type usage is nullable.</param> /// <param name="typeNameHint">The type name hint to use when generating the type and the type name is missing.</param> /// <param name="checkForExistingSchema">Checks whether a named schema is already registered.</param> /// <returns>The type name.</returns> public string Resolve(JsonSchema schema, bool isNullable, string typeNameHint, bool checkForExistingSchema) { if (schema == null) { throw new ArgumentNullException(nameof(schema)); } schema = GetResolvableSchema(schema); if (schema == ExceptionSchema) { return("System.Exception"); } // Primitive schemas (no new type) if (schema.ActualTypeSchema.IsAnyType && !schema.HasReference) { return(Settings.AnyType); } var type = schema.ActualTypeSchema.Type; if (type == JsonObjectType.None && schema.ActualTypeSchema.IsEnumeration) { type = schema.ActualTypeSchema.Enumeration.All(v => v is int) ? JsonObjectType.Integer : JsonObjectType.String; } if (type.HasFlag(JsonObjectType.Number)) { return(ResolveNumber(schema.ActualTypeSchema, isNullable)); } if (type.HasFlag(JsonObjectType.Integer) && !schema.ActualTypeSchema.IsEnumeration) { return(ResolveInteger(schema.ActualTypeSchema, isNullable, typeNameHint)); } if (type.HasFlag(JsonObjectType.Boolean)) { return(ResolveBoolean(isNullable)); } if (type.HasFlag(JsonObjectType.String) && !schema.ActualTypeSchema.IsEnumeration) { return(ResolveString(schema.ActualTypeSchema, isNullable, typeNameHint)); } if (schema.IsBinary) { return("byte[]"); } // Type generating schemas if (schema.Type.HasFlag(JsonObjectType.Array)) { return(ResolveArrayOrTuple(schema)); } if (schema.IsDictionary) { return(ResolveDictionary(schema)); } if (schema.ActualTypeSchema.IsEnumeration) { return(GetOrGenerateTypeName(schema, typeNameHint) + (isNullable ? "?" : string.Empty)); } return(GetOrGenerateTypeName(schema, typeNameHint)); }
/// <summary>Initializes a new instance of the <see cref="CSharpTypeResolver"/> class.</summary> /// <param name="settings">The generator settings.</param> /// <param name="exceptionSchema">The exception type schema.</param> public CSharpTypeResolver(CSharpGeneratorSettings settings, JsonSchema exceptionSchema) : base(settings) { Settings = settings; ExceptionSchema = exceptionSchema; }
public static JsonSchemaProperty ArrayProperty(JsonSchema item, string?description = null, bool isRequired = false) { return(Enrich(new JsonSchemaProperty { Type = JsonObjectType.Array, Item = item }, description, isRequired)); }
/// <summary>Resolves and possibly generates the specified schema.</summary> /// <param name="schema">The schema.</param> /// <param name="isNullable">Specifies whether the given type usage is nullable.</param> /// <param name="typeNameHint">The type name hint to use when generating the type and the type name is missing.</param> /// <param name="checkForExistingSchema">Checks whether a named schema is already registered.</param> /// <returns>The type name.</returns> public string Resolve(JsonSchema schema, bool isNullable, string typeNameHint, bool checkForExistingSchema) { if (schema == null) { throw new ArgumentNullException(nameof(schema)); } schema = GetResolvableSchema(schema); if (schema == ExceptionSchema) { return("System.Exception"); } // Primitive schemas (no new type) if (Settings.GenerateOptionalPropertiesAsNullable && schema is JsonSchemaProperty property && !property.IsRequired) { isNullable = true; } if (schema.ActualTypeSchema.IsAnyType && schema.InheritedSchema == null && // not in inheritance hierarchy schema.AllOf.Count == 0 && !Types.Keys.Contains(schema) && !schema.HasReference) { return(Settings.AnyType); } var type = schema.ActualTypeSchema.Type; if (type == JsonObjectType.None && schema.ActualTypeSchema.IsEnumeration) { type = schema.ActualTypeSchema.Enumeration.All(v => v is int) ? JsonObjectType.Integer : JsonObjectType.String; } if (type.HasFlag(JsonObjectType.Number)) { return(ResolveNumber(schema.ActualTypeSchema, isNullable)); } if (type.HasFlag(JsonObjectType.Integer) && !schema.ActualTypeSchema.IsEnumeration) { return(ResolveInteger(schema.ActualTypeSchema, isNullable, typeNameHint)); } if (type.HasFlag(JsonObjectType.Boolean)) { return(ResolveBoolean(isNullable)); } if (schema.IsBinary) { return("byte[]"); } if (type.HasFlag(JsonObjectType.String) && !schema.ActualTypeSchema.IsEnumeration) { return(ResolveString(schema.ActualTypeSchema, isNullable, typeNameHint)); } // Type generating schemas if (schema.Type.HasFlag(JsonObjectType.Array)) { return(ResolveArrayOrTuple(schema)); } if (schema.IsDictionary) { return(ResolveDictionary(schema)); } if (schema.ActualTypeSchema.IsEnumeration) { return(GetOrGenerateTypeName(schema, typeNameHint) + (isNullable ? "?" : string.Empty)); } return(GetOrGenerateTypeName(schema, typeNameHint)); }
/// <summary> /// Determines if the schema should be represented as a SimpleContentRestriction in the XSD. /// </summary> /// <param name="schema">The Json Schema to analyze.</param> /// <returns>True if it should be represented as a SimpleContentRestriction in the XSD; otherwise, false.</returns> protected bool IsValidSimpleContentRestriction(JsonSchema schema) { if (!HasSingleAllOf(schema)) { return(false); } var allOf = schema.GetKeyword <AllOfKeyword>(); var baseReferenceSchemas = allOf.Schemas.Where(s => s.HasKeyword <RefKeyword>()).ToList(); if (baseReferenceSchemas.Count != 1) { return(false); } var baseReferenceSchema = baseReferenceSchemas[0]; var baseSchema = FollowReference(baseReferenceSchema.GetKeyword <RefKeyword>()); // Make sure base is valid for SimpleContent restriction if (!IsValidSimpleContentExtension(baseSchema) && !IsValidSimpleContentRestriction(baseSchema)) { return(false); } var propertiesSchemas = allOf.Schemas.Where(s => s.HasKeyword <PropertiesKeyword>()).ToList(); // Don't allow extra subschemas not used in the pattern if (propertiesSchemas.Count + 1 != allOf.Schemas.Count) { return(false); } // All restriction properties must match properties from base type(s) var basePropertyNames = new HashSet <string>(); while (!IsValidSimpleType(baseSchema)) { foreach (var(propertyName, _) in FindSimpleContentProperties(baseSchema)) { basePropertyNames.Add(propertyName); } if (!baseSchema.TryGetKeyword(out AllOfKeyword baseAllOf)) { break; } var baseRefSchema = baseAllOf.Schemas .SingleOrDefault(s => s.HasKeyword <RefKeyword>()) ?.GetKeyword <RefKeyword>(); if (baseRefSchema == null) { break; } baseSchema = FollowReference(baseRefSchema); } var hasValueProperty = false; foreach (var(propertyName, propertySchema) in propertiesSchemas.SelectMany(ps => ps.GetKeyword <PropertiesKeyword>().Properties.Select(prop => (prop.Key, prop.Value)))) { if (!basePropertyNames.Contains(propertyName)) { // Can't restrict a property that is not present in base types, this is not a valid simple content restriction return(false); } var propertyTargetSchema = FollowReferencesIfAny(propertySchema); if (!hasValueProperty && propertyName == "value") { // "value" property hasValueProperty = true; // "value" property cannot be an attribute if (propertySchema.HasKeyword <XsdAttributeKeyword>()) { return(false); } } else { // restriction property must be an attribute if (!propertySchema.HasKeyword <XsdAttributeKeyword>()) { return(false); } } if (!IsValidSimpleTypeOrSimpleTypeRestriction(propertyTargetSchema) && !IsPlainRestrictionSchema(propertyTargetSchema)) { return(false); } } return(hasValueProperty); }
/// <summary> /// Determines if the schema should be represented as a SimpleContentExtension in the XSD. /// </summary> /// <param name="schema">The Json Schema to analyze.</param> /// <returns>True if it should be represented as a SimpleContentExtension in the XSD; otherwise, false.</returns> protected bool IsValidSimpleContentExtension(JsonSchema schema) { // Exclude schemas with groupings if (schema.HasAnyOfKeywords( typeof(AllOfKeyword), typeof(OneOfKeyword), typeof(AnyOfKeyword), typeof(IfKeyword), typeof(ThenKeyword), typeof(ElseKeyword), typeof(NotKeyword))) { return(false); } if (!schema.TryGetKeyword(out PropertiesKeyword properties)) { return(false); } // One of the properties must be named value if (!properties.Properties.TryGetValue("value", out var valuePropertySchema)) { return(false); } // It must not be marked as attribute if (valuePropertySchema.GetKeyword <XsdAttributeKeyword>()?.Value == true) { return(false); } // follow any $ref keywords to validate against the actual subschema while (valuePropertySchema.TryGetKeyword(out RefKeyword reference)) { valuePropertySchema = FollowReference(reference); } // And it must be a valid SimpleType or a reference to a valid SimpleType if (!IsValidSimpleTypeOrSimpleTypeRestriction(valuePropertySchema)) { return(false); } // All other properties must be attributes var attributePropertiesCount = properties.Properties.Values.Count(prop => { var typeSchema = prop; // follow any $ref keywords to validate against the actual subschema while (typeSchema.TryGetKeyword(out RefKeyword reference)) { typeSchema = FollowReference(reference); } return(IsValidSimpleTypeOrSimpleTypeRestriction(typeSchema) && prop.HasKeyword <XsdAttributeKeyword>(kw => kw.Value)); }); if (attributePropertiesCount != (properties.Properties.Count - 1)) { return(false); } return(true); }
/// <inheritdoc/> public abstract JsonSchemaXsdMetadata AnalyzeSchema(JsonSchema schema, Uri uri);
/// <summary> /// Determines if a schema has a type keyword with null as it's value in combination with other types. /// </summary> /// <param name="schema">The Json Schema to analyze.</param> /// <returns>True if the type keyword has Null type in combination with other types; otherwise, false.</returns> protected static bool HasTypeKeywordWithNullAndOtherTypes(JsonSchema schema) { return(schema.TryGetKeyword(out TypeKeyword typeKeywordSingle) && typeKeywordSingle.Type.HasFlag(SchemaValueType.Null) && typeKeywordSingle.Type > SchemaValueType.Null); }
/// <summary> /// Determines if a schema is a reference schema or not. /// A reference schema is a schema that has the $ref keyword. /// For further reference see https://json-schema.org/understanding-json-schema/structuring.html#ref /// </summary> /// <param name="schema">The Json Schema to analyze.</param> /// <returns></returns> protected static bool IsRefSchema(JsonSchema schema) { return(schema.HasKeyword <RefKeyword>()); }
public void EnumHint_WildCard() { const string SchemaText = @"{ ""type"": ""object"", ""properties"": { ""def1Prop"": { ""$ref"": ""#/definitions/def1"" }, ""def2Prop"": { ""$ref"": ""#/definitions/def2"" } }, ""definitions"": { ""def1"": { ""type"": ""object"", ""properties"": { ""backgroundColor"": { ""type"": ""string"", ""enum"": [ ""red"", ""green"", ""blue"" ] } } }, ""def2"": { ""type"": ""object"", ""properties"": { ""backgroundColor"": { ""type"": ""string"", ""enum"": [ ""red"", ""green"", ""blue"" ] } } } } }"; const string HintsText = @"{ ""*.BackgroundColor"": [ { ""kind"": ""EnumHint"", ""arguments"": { ""typeName"": ""Color"" } } ] }"; const string RootClassText = @"using System; using System.CodeDom.Compiler; using System.Runtime.Serialization; namespace N { [DataContract] [GeneratedCode(""Microsoft.Json.Schema.ToDotNet"", """ + VersionConstants.FileVersion + @""")] public partial class C { [DataMember(Name = ""def1Prop"", IsRequired = false, EmitDefaultValue = false)] public Def1 Def1Prop { get; set; } [DataMember(Name = ""def2Prop"", IsRequired = false, EmitDefaultValue = false)] public Def2 Def2Prop { get; set; } } }"; const string Def1ClassText = @"using System; using System.CodeDom.Compiler; using System.Runtime.Serialization; namespace N { [DataContract] [GeneratedCode(""Microsoft.Json.Schema.ToDotNet"", """ + VersionConstants.FileVersion + @""")] public partial class Def1 { [DataMember(Name = ""backgroundColor"", IsRequired = false, EmitDefaultValue = false)] public Color BackgroundColor { get; set; } } }"; const string Def2ClassText = @"using System; using System.CodeDom.Compiler; using System.Runtime.Serialization; namespace N { [DataContract] [GeneratedCode(""Microsoft.Json.Schema.ToDotNet"", """ + VersionConstants.FileVersion + @""")] public partial class Def2 { [DataMember(Name = ""backgroundColor"", IsRequired = false, EmitDefaultValue = false)] public Color BackgroundColor { get; set; } } }"; const string EnumText = @"using System.CodeDom.Compiler; namespace N { [GeneratedCode(""Microsoft.Json.Schema.ToDotNet"", """ + VersionConstants.FileVersion + @""")] public enum Color { Red, Green, Blue } }"; Settings.HintDictionary = new HintDictionary(HintsText); var generator = new DataModelGenerator(Settings, TestFileSystem.FileSystem); JsonSchema schema = SchemaReader.ReadSchema(SchemaText, TestUtil.TestFilePath); generator.Generate(schema); string primaryOutputFilePath = TestFileSystem.MakeOutputFilePath(Settings.RootClassName); string enumFilePath = TestFileSystem.MakeOutputFilePath("Color"); string def1FilePath = TestFileSystem.MakeOutputFilePath("Def1"); string def2FilePath = TestFileSystem.MakeOutputFilePath("Def2"); var expectedOutputFiles = new List <string> { primaryOutputFilePath, enumFilePath, def1FilePath, def2FilePath }; TestFileSystem.Files.Count.Should().Be(expectedOutputFiles.Count); TestFileSystem.Files.Should().OnlyContain(key => expectedOutputFiles.Contains(key)); TestFileSystem[primaryOutputFilePath].Should().Be(RootClassText); TestFileSystem[enumFilePath].Should().Be(EnumText); TestFileSystem[def1FilePath].Should().Be(Def1ClassText); TestFileSystem[def2FilePath].Should().Be(Def2ClassText); }
/// <summary>Gets the enum default value.</summary> /// <param name="schema">The schema.</param> /// <param name="actualSchema">The actual schema.</param> /// <param name="typeNameHint">The type name hint.</param> /// <param name="typeResolver">The type resolver.</param> /// <returns>The enum default value.</returns> protected override string GetEnumDefaultValue(JsonSchema schema, JsonSchema actualSchema, string typeNameHint, TypeResolverBase typeResolver) { return(_settings.Namespace + "." + base.GetEnumDefaultValue(schema, actualSchema, typeNameHint, typeResolver)); }
public void EqualsWithString() { JsonSchema lhs = new JsonSchema(); Assert.False(lhs.Equals("Not Equal")); }
public void WriteSchema(JsonSchema schema) { ValidationUtils.ArgumentNotNull(schema, "schema"); if (!_resolver.LoadedSchemas.Contains(schema)) _resolver.LoadedSchemas.Add(schema); _writer.WriteStartObject(); WritePropertyIfNotNull(_writer, JsonSchemaConstants.IdPropertyName, schema.Id); WritePropertyIfNotNull(_writer, JsonSchemaConstants.TitlePropertyName, schema.Title); WritePropertyIfNotNull(_writer, JsonSchemaConstants.DescriptionPropertyName, schema.Description); WritePropertyIfNotNull(_writer, JsonSchemaConstants.RequiredPropertyName, schema.Required); WritePropertyIfNotNull(_writer, JsonSchemaConstants.ReadOnlyPropertyName, schema.ReadOnly); WritePropertyIfNotNull(_writer, JsonSchemaConstants.HiddenPropertyName, schema.Hidden); WritePropertyIfNotNull(_writer, JsonSchemaConstants.TransientPropertyName, schema.Transient); if (schema.Type != null) WriteType(JsonSchemaConstants.TypePropertyName, _writer, schema.Type.Value); if (!schema.AllowAdditionalProperties) { _writer.WritePropertyName(JsonSchemaConstants.AdditionalPropertiesPropertyName); _writer.WriteValue(schema.AllowAdditionalProperties); } else { if (schema.AdditionalProperties != null) { _writer.WritePropertyName(JsonSchemaConstants.AdditionalPropertiesPropertyName); ReferenceOrWriteSchema(schema.AdditionalProperties); } } if (!schema.AllowAdditionalItems) { _writer.WritePropertyName(JsonSchemaConstants.AdditionalItemsPropertyName); _writer.WriteValue(schema.AllowAdditionalItems); } else { if (schema.AdditionalItems != null) { _writer.WritePropertyName(JsonSchemaConstants.AdditionalItemsPropertyName); ReferenceOrWriteSchema(schema.AdditionalItems); } } WriteSchemaDictionaryIfNotNull(_writer, JsonSchemaConstants.PropertiesPropertyName, schema.Properties); WriteSchemaDictionaryIfNotNull(_writer, JsonSchemaConstants.PatternPropertiesPropertyName, schema.PatternProperties); WriteItems(schema); WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumPropertyName, schema.Minimum); WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumPropertyName, schema.Maximum); WritePropertyIfNotNull(_writer, JsonSchemaConstants.ExclusiveMinimumPropertyName, schema.ExclusiveMinimum); WritePropertyIfNotNull(_writer, JsonSchemaConstants.ExclusiveMaximumPropertyName, schema.ExclusiveMaximum); WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumLengthPropertyName, schema.MinimumLength); WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumLengthPropertyName, schema.MaximumLength); WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumItemsPropertyName, schema.MinimumItems); WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumItemsPropertyName, schema.MaximumItems); WritePropertyIfNotNull(_writer, JsonSchemaConstants.DivisibleByPropertyName, schema.DivisibleBy); WritePropertyIfNotNull(_writer, JsonSchemaConstants.FormatPropertyName, schema.Format); WritePropertyIfNotNull(_writer, JsonSchemaConstants.PatternPropertyName, schema.Pattern); if (schema.Enum != null) { _writer.WritePropertyName(JsonSchemaConstants.EnumPropertyName); _writer.WriteStartArray(); foreach (JToken token in schema.Enum) { token.WriteTo(_writer); } _writer.WriteEndArray(); } if (schema.Default != null) { _writer.WritePropertyName(JsonSchemaConstants.DefaultPropertyName); schema.Default.WriteTo(_writer); } if (schema.Disallow != null) WriteType(JsonSchemaConstants.DisallowPropertyName, _writer, schema.Disallow.Value); if (schema.Extends != null && schema.Extends.Count > 0) { _writer.WritePropertyName(JsonSchemaConstants.ExtendsPropertyName); if (schema.Extends.Count == 1) { ReferenceOrWriteSchema(schema.Extends[0]); } else { _writer.WriteStartArray(); foreach (JsonSchema jsonSchema in schema.Extends) { ReferenceOrWriteSchema(jsonSchema); } _writer.WriteEndArray(); } } _writer.WriteEndObject(); }
private static List <(string PropertyName, JsonSchema PropertySchema)> FindSimpleContentProperties(JsonSchema schema) { var properties = new List <(string PropertyName, JsonSchema PropertySchema)>(); if (HasSingleAllOf(schema)) { foreach (var propertiesSchema in schema.GetKeyword <AllOfKeyword>().Schemas.Where(s => s.HasKeyword <PropertiesKeyword>())) { var propertiesKeyword = propertiesSchema.GetKeyword <PropertiesKeyword>(); properties.AddRange(propertiesKeyword.Properties.Select(prop => (prop.Key, prop.Value))); } } else if (schema.TryGetKeyword(out PropertiesKeyword propertiesKeyword)) { properties.AddRange(propertiesKeyword.Properties.Select(prop => (prop.Key, prop.Value))); } return(properties); }
public void AddAdditionalItems(JsonSchemaNode parentNode, JsonSchema schema) { parentNode.AdditionalItems = AddSchema(parentNode.AdditionalItems, schema); }
/// <summary> /// Primary method to call for analyzing a Json Schema. /// </summary> /// <param name="path">The path to start analyzing. Normally this should be the root path when calling this method ie. '#'</param> /// <param name="schema">The Json Schema to analyze.</param> protected void AnalyzeSchema(JsonPointer path, JsonSchema schema) { if (TryParseAsNillableElement(schema, out var valueSchema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.Nillable); if (valueSchema != null) { AnalyzeSchema(path, valueSchema); return; } } if (TryParseAsArray(schema, out var itemSchema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.Array); AnalyzeSchema(path, itemSchema); return; } // Follow all references, this will mark the schema as the type referenced if it has a $ref keyword // This will analyze some schemas multiple times and can be optimized if needed schema = FollowReferencesIfAny(schema); if (IsValidSimpleType(schema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.SimpleType); if (IsValidAttribute(schema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.Attribute); } if (IsValidUnhandledAttribute(schema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.UnhandledAttribute); } } if (IsValidSimpleTypeRestriction(schema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.SimpleType); Metadata.AddCompatibleTypes(path, CompatibleXsdType.SimpleTypeRestriction); } if (IsValidComplexType(schema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.ComplexType); } if (IsValidSimpleContentExtension(schema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.SimpleContentExtension); } if (IsValidSimpleContentRestriction(schema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.SimpleContentRestriction); } if (IsValidComplexContentExtension(path, schema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.ComplexContent); Metadata.AddCompatibleTypes(path, CompatibleXsdType.ComplexContentExtension); } if (schema.Keywords != null) { foreach (var keyword in schema.Keywords) { var keywordPath = path.Combine(JsonPointer.Parse($"/{keyword.Keyword()}")); AnalyzeKeyword(keywordPath, keyword); } } if (IsValidUnhandledAttribute(schema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.UnhandledAttribute); } if (IsValidUnhandledEnumAttribute(schema)) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.UnhandledEnumAttribute); } // Add "unknown" if no other was added on this path if (Metadata.GetCompatibleTypes(path).Count == 0) { Metadata.AddCompatibleTypes(path, CompatibleXsdType.Unknown); } }
public void UserModelTest() { var schema = JsonSchema.FromType <UserModel>().ToJson(); Approvals.Verify(schema); }
public void ReaderPerformance() { string json = @"[ { ""id"": 2, ""name"": ""An ice sculpture"", ""price"": 12.50, ""tags"": [""cold"", ""ice""], ""dimensions"": { ""length"": 7.0, ""width"": 12.0, ""height"": 9.5 }, ""warehouseLocation"": { ""latitude"": -78.75, ""longitude"": 20.4 } }, { ""id"": 3, ""name"": ""A blue mouse"", ""price"": 25.50, ""dimensions"": { ""length"": 3.1, ""width"": 1.0, ""height"": 1.0 }, ""warehouseLocation"": { ""latitude"": 54.4, ""longitude"": -32.7 } } ]"; JsonSchema schema = JsonSchema.Parse(@"{ ""$schema"": ""http://json-schema.org/draft-04/schema#"", ""title"": ""Product set"", ""type"": ""array"", ""items"": { ""title"": ""Product"", ""type"": ""object"", ""properties"": { ""id"": { ""description"": ""The unique identifier for a product"", ""type"": ""number"", ""required"": true }, ""name"": { ""type"": ""string"", ""required"": true }, ""price"": { ""type"": ""number"", ""minimum"": 0, ""exclusiveMinimum"": true, ""required"": true }, ""tags"": { ""type"": ""array"", ""items"": { ""type"": ""string"" }, ""minItems"": 1, ""uniqueItems"": true }, ""dimensions"": { ""type"": ""object"", ""properties"": { ""length"": {""type"": ""number"",""required"": true}, ""width"": {""type"": ""number"",""required"": true}, ""height"": {""type"": ""number"",""required"": true} } }, ""warehouseLocation"": { ""description"": ""A geographical coordinate"", ""type"": ""object"", ""properties"": { ""latitude"": { ""type"": ""number"" }, ""longitude"": { ""type"": ""number"" } } } } } }"); using (var tester = new PerformanceTester("Reader")) { for (int i = 0; i < 5000; i++) { JsonTextReader reader = new JsonTextReader(new StringReader(json)); JsonValidatingReader validatingReader = new JsonValidatingReader(reader); validatingReader.Schema = schema; while (validatingReader.Read()) { } } } }
/// <summary>Resolves and possibly generates the specified schema.</summary> /// <param name="schema">The schema.</param> /// <param name="isNullable">Specifies whether the given type usage is nullable.</param> /// <param name="typeNameHint">The type name hint to use when generating the type and the type name is missing.</param> /// <returns>The type name.</returns> public override string Resolve(JsonSchema schema, bool isNullable, string typeNameHint) { return(Resolve(schema, isNullable, typeNameHint, true)); }
public void ExtendedComplex() { string first = @"{ ""id"":""first"", ""type"":""object"", ""properties"": { ""firstproperty"":{""type"":""string""}, ""secondproperty"":{""type"":""string"",""maxLength"":10}, ""thirdproperty"":{ ""type"":""object"", ""properties"": { ""thirdproperty_firstproperty"":{""type"":""string"",""maxLength"":10,""minLength"":7} } } }, ""additionalProperties"":{} }"; string second = @"{ ""id"":""second"", ""type"":""object"", ""extends"":{""$ref"":""first""}, ""properties"": { ""secondproperty"":{""type"":""any""}, ""thirdproperty"":{ ""extends"":{ ""properties"": { ""thirdproperty_firstproperty"":{""maxLength"":9,""minLength"":6,""pattern"":""hi2u""} }, ""additionalProperties"":{""maxLength"":9,""minLength"":6,""enum"":[""one"",""two""]} }, ""type"":""object"", ""properties"": { ""thirdproperty_firstproperty"":{""pattern"":""hi""} }, ""additionalProperties"":{""type"":""string"",""enum"":[""two"",""three""]} }, ""fourthproperty"":{""type"":""string""} }, ""additionalProperties"":false }"; JsonSchemaResolver resolver = new JsonSchemaResolver(); JsonSchema firstSchema = JsonSchema.Parse(first, resolver); JsonSchema secondSchema = JsonSchema.Parse(second, resolver); JsonSchemaModelBuilder modelBuilder = new JsonSchemaModelBuilder(); JsonSchemaModel model = modelBuilder.Build(secondSchema); Assert.AreEqual(4, model.Properties.Count); Assert.AreEqual(JsonSchemaType.String, model.Properties["firstproperty"].Type); Assert.AreEqual(JsonSchemaType.String, model.Properties["secondproperty"].Type); Assert.AreEqual(10, model.Properties["secondproperty"].MaximumLength); Assert.AreEqual(null, model.Properties["secondproperty"].Enum); Assert.AreEqual(null, model.Properties["secondproperty"].Patterns); Assert.AreEqual(JsonSchemaType.Object, model.Properties["thirdproperty"].Type); Assert.AreEqual(3, model.Properties["thirdproperty"].AdditionalProperties.Enum.Count); Assert.AreEqual("two", (string)model.Properties["thirdproperty"].AdditionalProperties.Enum[0]); Assert.AreEqual("three", (string)model.Properties["thirdproperty"].AdditionalProperties.Enum[1]); Assert.AreEqual("one", (string)model.Properties["thirdproperty"].AdditionalProperties.Enum[2]); Assert.AreEqual(JsonSchemaType.String, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Type); Assert.AreEqual(9, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].MaximumLength); Assert.AreEqual(7, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].MinimumLength); Assert.AreEqual(2, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Patterns.Count); Assert.AreEqual("hi", model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Patterns[0]); Assert.AreEqual("hi2u", model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Patterns[1]); Assert.AreEqual(null, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Properties); Assert.AreEqual(null, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].Items); Assert.AreEqual(null, model.Properties["thirdproperty"].Properties["thirdproperty_firstproperty"].AdditionalProperties); }
public void ImportExportTest() { var path = AliciaPath; var context = new VRMImporterContext(); context.ParseGlb(File.ReadAllBytes(path)); context.Load(); context.ShowMeshes(); context.EnableUpdateWhenOffscreen(); using (new ActionDisposer(() => { GameObject.DestroyImmediate(context.Root); })) { var importedJson = JsonParser.Parse(context.Json); importedJson.SetValue("/extensions/VRM/exporterVersion", VRMVersion.VRM_VERSION); importedJson.SetValue("/asset/generator", UniGLTF.UniGLTFVersion.UNIGLTF_VERSION); importedJson.SetValue("/scene", 0); importedJson.SetValue("/materials/*/doubleSided", false); //importJson.SetValue("/materials/*/pbrMetallicRoughness/roughnessFactor", 0); //importJson.SetValue("/materials/*/pbrMetallicRoughness/baseColorFactor", new float[] { 1, 1, 1, 1 }); importedJson.SetValue("/accessors/*/normalized", false); importedJson.RemoveValue(Utf8String.From("/nodes/*/extras")); /* * importJson.SetValue("/bufferViews/12/byteStride", 4); * importJson.SetValue("/bufferViews/13/byteStride", 4); * importJson.SetValue("/bufferViews/14/byteStride", 4); * importJson.SetValue("/bufferViews/15/byteStride", 4); * importJson.SetValue("/bufferViews/22/byteStride", 4); * importJson.SetValue("/bufferViews/29/byteStride", 4); * importJson.SetValue("/bufferViews/45/byteStride", 4); * importJson.SetValue("/bufferViews/46/byteStride", 4); * importJson.SetValue("/bufferViews/47/byteStride", 4); * importJson.SetValue("/bufferViews/201/byteStride", 4); * importJson.SetValue("/bufferViews/202/byteStride", 4); * importJson.SetValue("/bufferViews/203/byteStride", 4); * importJson.SetValue("/bufferViews/204/byteStride", 4); * importJson.SetValue("/bufferViews/211/byteStride", 4); * importJson.SetValue("/bufferViews/212/byteStride", 4); * importJson.SetValue("/bufferViews/213/byteStride", 4); * importJson.SetValue("/bufferViews/214/byteStride", 4); * importJson.SetValue("/bufferViews/215/byteStride", 4); * importJson.SetValue("/bufferViews/243/byteStride", 4); * importJson.SetValue("/bufferViews/247/byteStride", 64); * importJson.SetValue("/bufferViews/248/byteStride", 64); * importJson.SetValue("/bufferViews/249/byteStride", 64); * importJson.SetValue("/bufferViews/250/byteStride", 64); * importJson.SetValue("/bufferViews/251/byteStride", 64); * importJson.SetValue("/bufferViews/252/byteStride", 64); * importJson.SetValue("/bufferViews/253/byteStride", 64); */ importedJson.RemoveValue(Utf8String.From("/bufferViews/*/byteStride")); var vrm = VRMExporter.Export(UniGLTF.MeshExportSettings.Default, context.Root); // TODO: Check contents in JSON /*var exportJson = */ JsonParser.Parse(vrm.ToJson()); // TODO: Check contents in JSON /*var newExportedJson = */ JsonParser.Parse(JsonSchema.FromType <glTF>().Serialize(vrm)); /* * foreach (var kv in importJson.Diff(exportJson)) * { * Debug.Log(kv); * } * * Assert.AreEqual(importJson, exportJson); */ } }
public void Process(DocumentProcessorContext context) { if (!_openApiOptions.ContentTypes.ProcessContentTypes) { return; } _contentDefinitionManager ??= _httpContextAccessor.HttpContext.RequestServices.GetRequiredService <IContentDefinitionManager>(); var contentElementDtoSchema = context.SchemaGenerator.Generate(typeof(ContentElementDto), context.SchemaResolver); // Due to issue with NJsonSchema we force set additional properties here to false // because it is defined on the base class. // cf. https://github.com/RicoSuter/NSwag/issues/2818 contentElementDtoSchema.AllowAdditionalProperties = false; var fieldDtoSchema = context.SchemaGenerator.Generate(typeof(ContentFieldDto), context.SchemaResolver); fieldDtoSchema.AllowAdditionalProperties = false; var ctds = _contentDefinitionManager.ListTypeDefinitions(); var allFieldDefinitions = ctds .SelectMany(x => x.Parts.SelectMany(p => p.PartDefinition.Fields)) .Select(x => x.FieldDefinition).ToLookup(x => x.Name, StringComparer.OrdinalIgnoreCase); // Process fields foreach (var contentFieldOption in _contentOptions.ContentFieldOptions) { if (!_openApiOptions.ContentTypes.IncludeAllFields) { if (!allFieldDefinitions.Contains(contentFieldOption.Type.Name)) { continue; } } if (_openApiOptions.ContentTypes.ExcludedFields.Any(x => string.Equals(x, contentFieldOption.Type.Name, StringComparison.OrdinalIgnoreCase))) { continue; } var fieldSchema = context.SchemaGenerator.Generate(contentFieldOption.Type, context.SchemaResolver); fieldSchema.AllOf.ElementAt(1).AllowAdditionalProperties = false; // remove first AllOf and reinsert the fieldDtoSchema as the ref. InsertDtoReferenceSchema(fieldSchema, fieldDtoSchema); // Change schema regisitration name to 'TextFieldDto' AlterSchemaDefinition(context, contentFieldOption.Type.Name, _openApiOptions.ContentTypes.SchemaNameExtension); } // Process Parts // Note we have to use the content definition manager here // because parts may be created dynamically. // We also include definitions for code only parts, like ContainedPart var contentItemSchema = context.SchemaResolver.GetSchema(typeof(ContentItem), false); // This should end up being ignored, because we remove it from the nswag.config var contentItemDtoSchema = context.SchemaGenerator.Generate(typeof(ContentItemDto), context.SchemaResolver); contentItemDtoSchema.AllowAdditionalProperties = false; //var contentItemDtoSchema = context.Document.Definitions["ContentItemDto"]; var partDtoSchema = context.SchemaGenerator.Generate(typeof(ContentPartDto), context.SchemaResolver); partDtoSchema.AllowAdditionalProperties = false; var allPartDefinitions = _contentDefinitionManager.ListPartDefinitions(); // Register code only parts first. foreach (var registeredPartOption in _contentOptions.ContentPartOptions) { // Is also registered in the part definitions. if (allPartDefinitions.Any(x => x.Name == registeredPartOption.Type.Name)) { continue; } // Has no fields as it is code only var partSchema = context.SchemaGenerator.Generate(registeredPartOption.Type, context.SchemaResolver); partSchema.AllOf.ElementAt(1).AllowAdditionalProperties = false; // remove first AllOf and reinsert the partDtoSchema as the ref. InsertDtoReferenceSchema(partSchema, partDtoSchema); // Use ActualProperties here, not Properties AlterArrayPropertiesToContentItemDtoSchema(partSchema.ActualProperties, contentItemSchema, contentItemDtoSchema); // Change schema regisitration name to 'ContainedPartDto' AlterSchemaDefinition(context, registeredPartOption.Type.Name, _openApiOptions.ContentTypes.SchemaNameExtension); } // Then register parts defined in the part definitions. foreach (var partDefinition in allPartDefinitions) { // check to see if it is a hard typed part. if (_contentOptions.ContentPartOptionsLookup.TryGetValue(partDefinition.Name, out var contentPartOption)) { var partSchema = context.SchemaGenerator.Generate(contentPartOption.Type, context.SchemaResolver); partSchema.AllOf.ElementAt(1).AllowAdditionalProperties = false; // remove first AllOf and reinsert the partDtoSchema as the ref. InsertDtoReferenceSchema(partSchema, partDtoSchema); //TODO test this, it's being added as a direct property // but the other properties are added as part of all of // so we might need to find all of index 1 and insert it there foreach (var field in partDefinition.Fields) { // Lookup field definition. if (context.Document.Definitions.TryGetValue(field.FieldDefinition.Name + _openApiOptions.ContentTypes.SchemaNameExtension, out var fieldSchema)) { // Add field as property. var propertySchema = new JsonSchemaProperty { Type = JsonObjectType.Object, IsNullableRaw = true }; propertySchema.OneOf.Add(new JsonSchema { Type = JsonObjectType.Object, Reference = fieldSchema.ActualSchema }); partSchema.Properties[field.Name] = propertySchema; } } foreach (var allOfSchema in partSchema.AllOf) { AlterArrayPropertiesToContentItemDtoSchema(allOfSchema.ActualProperties, contentItemSchema, contentItemDtoSchema); } // Change schema regisitration name to 'HtmlPartDto' AlterSchemaDefinition(context, contentPartOption.Type.Name, _openApiOptions.ContentTypes.SchemaNameExtension); } else // This builds dynamic parts. { // We need to skip registrations for type definition parts. if (ctds.Any(x => x.Name == partDefinition.Name)) { continue; } var partReferenceSchema = new JsonSchema { Type = JsonObjectType.Object, Reference = partDtoSchema.ActualSchema, AllowAdditionalProperties = false }; var partSchema = new JsonSchema { Type = JsonObjectType.Object, AllowAdditionalProperties = false }; partSchema.AllOf.Add(partReferenceSchema); foreach (var field in partDefinition.Fields) { // Lookup field definition. if (context.Document.Definitions.TryGetValue(field.FieldDefinition.Name + _openApiOptions.ContentTypes.SchemaNameExtension, out var fieldSchema)) { // Add field as property. var propertySchema = new JsonSchemaProperty { Type = JsonObjectType.Object, IsNullableRaw = true }; propertySchema.OneOf.Add(new JsonSchema { Type = JsonObjectType.Object, Reference = fieldSchema.ActualSchema }); partSchema.Properties[field.Name] = propertySchema; } } context.Document.Definitions[partDefinition.Name + _openApiOptions.ContentTypes.SchemaNameExtension] = partSchema; } } // Content Types var typeDtoSchema = context.SchemaGenerator.Generate(typeof(ContentItemDto), context.SchemaResolver); typeDtoSchema.AllowAdditionalProperties = false; typeDtoSchema.ActualTypeSchema.DiscriminatorObject = new OpenApiDiscriminator { //PropertyName = "discriminator", PropertyName = "ContentType", // TODO a custom one of these might help create types automatically. // Particularly useful for Flow.ContentItems etc. JsonInheritanceConverter = new JsonInheritanceConverter("ContentType") }; foreach (var ctd in ctds) { if (_openApiOptions.ContentTypes.ExcludedTypes.Any(x => string.Equals(x, ctd.Name))) { continue; } var typeReferenceSchema = new JsonSchema { Type = JsonObjectType.Object, Reference = typeDtoSchema.ActualSchema, AllowAdditionalProperties = false }; var typeSchema = new JsonSchema { Type = JsonObjectType.Object, AllowAdditionalProperties = false }; typeSchema.AllOf.Add(typeReferenceSchema); var typeFieldPartDefinition = ctd.Parts.FirstOrDefault(x => x.PartDefinition.Name == ctd.Name); // Not all content types will have a 'FieldDefinitionPart' until fields are added. if (typeFieldPartDefinition != null) { // Add Field Part container var partSchema = new JsonSchema { Type = JsonObjectType.Object, AllowAdditionalProperties = false }; var partReferenceSchema = new JsonSchema { Type = JsonObjectType.Object, AllowAdditionalProperties = false, Reference = partDtoSchema.ActualSchema }; partSchema.AllOf.Add(partReferenceSchema); // TODO move to method foreach (var field in typeFieldPartDefinition.PartDefinition.Fields) { // Lookup field definition. if (context.Document.Definitions.TryGetValue(field.FieldDefinition.Name + _openApiOptions.ContentTypes.SchemaNameExtension, out var fieldSchema)) { // Add field as property. var propertySchema = new JsonSchemaProperty { Type = JsonObjectType.Object, IsNullableRaw = true }; propertySchema.OneOf.Add(new JsonSchema { Type = JsonObjectType.Object, Reference = fieldSchema.ActualSchema }); partSchema.Properties[field.Name] = propertySchema; } } // Don't add "Part" here because users often create their own TypePart. context.Document.Definitions[ctd.Name + _openApiOptions.ContentTypes.SchemaNameExtension] = partSchema; // Add fieldpart as property. var typePropertySchema = new JsonSchemaProperty { Type = JsonObjectType.Object, IsNullableRaw = true }; typePropertySchema.OneOf.Add(new JsonSchema { Type = JsonObjectType.Object, Reference = partSchema.ActualSchema }); typeSchema.Properties[typeFieldPartDefinition.Name] = typePropertySchema; } // Add all other parts var parts = ctd.Parts.Where(x => x.PartDefinition.Name != ctd.Name); foreach (var partDefinition in parts) { // Lookup part definition. if (context.Document.Definitions.TryGetValue(partDefinition.PartDefinition.Name + _openApiOptions.ContentTypes.SchemaNameExtension, out var typePartSchema)) { // Add part as property. var propertySchema = new JsonSchemaProperty { Type = JsonObjectType.Object, IsNullableRaw = true }; propertySchema.OneOf.Add(new JsonSchema { Type = JsonObjectType.Object, Reference = typePartSchema.ActualSchema }); typeSchema.Properties[partDefinition.Name] = propertySchema; } } // Add final definition. context.Document.Definitions[ctd.Name + _openApiOptions.ContentTypes.SchemaTypeNameExtension + _openApiOptions.ContentTypes.SchemaNameExtension] = typeSchema; // Add discriminator mappings to actual type schema typeDtoSchema.ActualTypeSchema.DiscriminatorObject.Mapping.Add( ctd.Name + _openApiOptions.ContentTypes.SchemaTypeNameExtension + _openApiOptions.ContentTypes.SchemaNameExtension, new JsonSchema { Reference = typeSchema } ); } }
public void AddPropertyWithWhitespacePropertyName() { JsonSchema jsonSchema = new JsonSchema(); Assert.Throws<ArgumentException>(() => { jsonSchema.AddProperty(" ", null); }); }
private static JsonSchemaProperty CreateFormDataProperty(OperationProcessorContext context, ExtendedApiParameterDescription extendedApiParameter, JsonSchema schema) { return(context.SchemaGenerator.GenerateWithReferenceAndNullability <JsonSchemaProperty>( extendedApiParameter.ApiParameter.Type.ToContextualType(extendedApiParameter.Attributes), context.SchemaResolver)); }
public void AddRequiredWithTwoValuesWhenSecondPropertyDoesntExist() { JsonSchema jsonSchema = new JsonSchema(); jsonSchema.AddProperty("a", new JsonSchema()); Assert.Throws<ArgumentException>(() => { jsonSchema.AddRequired("a", "b"); }); }
protected void ValidateConfiguration() { // if no AntimalwareConfiguration XmlDocument was provided, use the AntimalwareConfigFile parameter if ((AntimalwareConfiguration == null) && (AntimalwareConfigFile != null)) { if ((!string.IsNullOrWhiteSpace(AntimalwareConfigFile)) && File.Exists(AntimalwareConfigFile)) { AntimalwareConfiguration = File.ReadAllText(AntimalwareConfigFile); } else { ThrowTerminatingError(new ErrorRecord( new Exception("ServiceExtensionCannotFindAntimalwareConfigFile"), string.Empty, ErrorCategory.InvalidData, null)); } } // validate json schema and check for antimalwareenabled value if (AntimalwareConfiguration != null) { JsonSchema v2Schema = JsonSchema.Parse(MicrosoftAntimalwareConfigJsonSchema); JObject json = JObject.Parse(AntimalwareConfiguration); if (json.IsValid(v2Schema)) { JToken tok; if (json != null) { if (json.TryGetValue("AntimalwareEnabled", out tok)) { isAntimalwareEnabled = (bool)tok; } } } else { ThrowTerminatingError(new ErrorRecord( new Exception("ServiceExtensionAntimalwareJsonConfigFailedSchemaValidation"), string.Empty, ErrorCategory.InvalidData, null)); } } // error no configuration was provided - error if this is not a case of disable, uninstall, or noconfig if (!isAntimalwareEnabled && ((!((Disable.IsPresent && Disable.ToBool()) || (Uninstall.IsPresent && Uninstall.ToBool()) || (NoConfig.IsPresent && NoConfig.ToBool()))))) { ThrowTerminatingError(new ErrorRecord( new Exception("JSON configuration is required and must specify \"AntimalwareEnabled\"=true"), string.Empty, ErrorCategory.InvalidData, null)); } // process Monitoring parameter if specified if (Monitoring != null) { switch (Monitoring.ToUpperInvariant()) { case "ON": monitoringAction = MonitoringActionType.Enable; break; case "OFF": monitoringAction = MonitoringActionType.Disable; break; default: break; } } }
public void EqualsWithNull() { JsonSchema lhs = new JsonSchema(); Assert.False(lhs.Equals(null)); }
private JsonSchema ResolveReferences(JsonSchema schema) { if (schema.DeferredReference != null) { string reference = schema.DeferredReference; bool locationReference = (reference.StartsWith("#", StringComparison.Ordinal)); if (locationReference) reference = UnescapeReference(reference); JsonSchema resolvedSchema = _resolver.GetSchema(reference); if (resolvedSchema == null) { if (locationReference) { string[] escapedParts = schema.DeferredReference.TrimStart('#').Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); JToken currentToken = _rootSchema; foreach (string escapedPart in escapedParts) { string part = UnescapeReference(escapedPart); if (currentToken.Type == JTokenType.Object) { currentToken = currentToken[part]; } else if (currentToken.Type == JTokenType.Array || currentToken.Type == JTokenType.Constructor) { int index; if (int.TryParse(part, out index) && index >= 0 && index < currentToken.Count()) currentToken = currentToken[index]; else currentToken = null; } if (currentToken == null) break; } if (currentToken != null) resolvedSchema = BuildSchema(currentToken); } if (resolvedSchema == null) throw new JsonException("Could not resolve schema reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, schema.DeferredReference)); } schema = resolvedSchema; } if (schema.ReferencesResolved) return schema; schema.ReferencesResolved = true; if (schema.Extends != null) { for (int i = 0; i < schema.Extends.Count; i++) { schema.Extends[i] = ResolveReferences(schema.Extends[i]); } } if (schema.Items != null) { for (int i = 0; i < schema.Items.Count; i++) { schema.Items[i] = ResolveReferences(schema.Items[i]); } } if (schema.AdditionalItems != null) schema.AdditionalItems = ResolveReferences(schema.AdditionalItems); if (schema.PatternProperties != null) { foreach (KeyValuePair<string, JsonSchema> patternProperty in schema.PatternProperties.ToList()) { schema.PatternProperties[patternProperty.Key] = ResolveReferences(patternProperty.Value); } } if (schema.Properties != null) { foreach (KeyValuePair<string, JsonSchema> property in schema.Properties.ToList()) { schema.Properties[property.Key] = ResolveReferences(property.Value); } } if (schema.AdditionalProperties != null) schema.AdditionalProperties = ResolveReferences(schema.AdditionalProperties); return schema; }
private JsonSchema BuildSchema(JToken token) { JObject schemaObject = token as JObject; if (schemaObject == null) throw JsonException.Create(token, token.Path, "Expected object while parsing schema object, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); JToken referenceToken; if (schemaObject.TryGetValue(JsonTypeReflector.RefPropertyName, out referenceToken)) { JsonSchema deferredSchema = new JsonSchema(); deferredSchema.DeferredReference = (string)referenceToken; return deferredSchema; } string location = token.Path.Replace(".", "/").Replace("[", "/").Replace("]", string.Empty); if (!string.IsNullOrEmpty(location)) location = "/" + location; location = "#" + location; JsonSchema existingSchema; if (_documentSchemas.TryGetValue(location, out existingSchema)) return existingSchema; Push(new JsonSchema { Location = location }); ProcessSchemaProperties(schemaObject); return Pop(); }
public SarifValidatorTests() { _jsonSchemaFilePath = Path.Combine(Environment.CurrentDirectory, JsonSchemaFile); string schemaText = File.ReadAllText(JsonSchemaFile); _schema = SchemaReader.ReadSchema(schemaText, JsonSchemaFile); }
public void AddItem(JsonSchemaNode parentNode, int index, JsonSchema schema) { JsonSchemaNode existingItemNode = (parentNode.Items.Count > index) ? parentNode.Items[index] : null; JsonSchemaNode newItemNode = AddSchema(existingItemNode, schema); if (!(parentNode.Items.Count > index)) { parentNode.Items.Add(newItemNode); } else { parentNode.Items[index] = newItemNode; } }
public void GenerateSchemaSerializable() { JsonSchemaGenerator generator = new JsonSchemaGenerator(); generator.ContractResolver = new DefaultContractResolver { IgnoreSerializableAttribute = false }; generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName; JsonSchema schema = generator.Generate(typeof(Version), true); string json = schema.ToString(); StringAssert.AreEqual(@"{ ""id"": ""System.Version"", ""type"": [ ""object"", ""null"" ], ""additionalProperties"": false, ""properties"": { ""_Major"": { ""required"": true, ""type"": ""integer"" }, ""_Minor"": { ""required"": true, ""type"": ""integer"" }, ""_Build"": { ""required"": true, ""type"": ""integer"" }, ""_Revision"": { ""required"": true, ""type"": ""integer"" } } }", json); JTokenWriter jsonWriter = new JTokenWriter(); JsonSerializer serializer = new JsonSerializer(); serializer.ContractResolver = new DefaultContractResolver { IgnoreSerializableAttribute = false }; serializer.Serialize(jsonWriter, new Version(1, 2, 3, 4)); List <string> errors = new List <string>(); jsonWriter.Token.Validate(schema, (sender, args) => errors.Add(args.Message)); Assert.AreEqual(0, errors.Count); StringAssert.AreEqual(@"{ ""_Major"": 1, ""_Minor"": 2, ""_Build"": 3, ""_Revision"": 4 }", jsonWriter.Token.ToString()); Version version = jsonWriter.Token.ToObject <Version>(serializer); Assert.AreEqual(1, version.Major); Assert.AreEqual(2, version.Minor); Assert.AreEqual(3, version.Build); Assert.AreEqual(4, version.Revision); }
private void WriteItems(JsonSchema schema) { if (schema.Items == null && !schema.PositionalItemsValidation) return; _writer.WritePropertyName(JsonSchemaConstants.ItemsPropertyName); if (!schema.PositionalItemsValidation) { if (schema.Items != null && schema.Items.Count > 0) { ReferenceOrWriteSchema(schema.Items[0]); } else { _writer.WriteStartObject(); _writer.WriteEndObject(); } return; } _writer.WriteStartArray(); if (schema.Items != null) { foreach (JsonSchema itemSchema in schema.Items) { ReferenceOrWriteSchema(itemSchema); } } _writer.WriteEndArray(); }
public JsonSchemaNode Combine(JsonSchema schema) { return new JsonSchemaNode(this, schema); }
public void AddProperty(IDictionary<string, JsonSchemaNode> target, string propertyName, JsonSchema schema) { JsonSchemaNode propertyNode; target.TryGetValue(propertyName, out propertyNode); target[propertyName] = AddSchema(propertyNode, schema); }
/// <summary> /// Validates the specified <see cref="JToken"/>. /// </summary> /// <param name="source">The source <see cref="JToken"/> to test.</param> /// <param name="schema">The schema to test with.</param> /// <param name="validationEventHandler">The validation event handler.</param> public static void Validate(this JToken source, JsonSchema schema, ValidationEventHandler validationEventHandler) { ValidationUtils.ArgumentNotNull(source, "source"); ValidationUtils.ArgumentNotNull(schema, "schema"); using (JsonValidatingReader reader = new JsonValidatingReader(source.CreateReader())) { reader.Schema = schema; if (validationEventHandler != null) reader.ValidationEventHandler += validationEventHandler; while (reader.Read()) { } } }
public void AddAdditionalProperties(JsonSchemaNode parentNode, JsonSchema schema) { parentNode.AdditionalProperties = AddSchema(parentNode.AdditionalProperties, schema); }
public void Extends_Multiple() { string json = @"{ ""type"":""object"", ""extends"":{""type"":""string""}, ""additionalProperties"":{""type"":""string""} }"; JsonSchema s = JsonSchema.Parse(json); StringWriter writer = new StringWriter(); JsonTextWriter jsonWriter = new JsonTextWriter(writer); jsonWriter.Formatting = Formatting.Indented; string newJson = s.ToString(); Assert.AreEqual(@"{ ""type"": ""object"", ""additionalProperties"": { ""type"": ""string"" }, ""extends"": { ""type"": ""string"" } }", newJson); json = @"{ ""type"":""object"", ""extends"":[{""type"":""string""}], ""additionalProperties"":{""type"":""string""} }"; s = JsonSchema.Parse(json); writer = new StringWriter(); jsonWriter = new JsonTextWriter(writer); jsonWriter.Formatting = Formatting.Indented; newJson = s.ToString(); Assert.AreEqual(@"{ ""type"": ""object"", ""additionalProperties"": { ""type"": ""string"" }, ""extends"": { ""type"": ""string"" } }", newJson); json = @"{ ""type"":""object"", ""extends"":[{""type"":""string""},{""type"":""object""}], ""additionalProperties"":{""type"":""string""} }"; s = JsonSchema.Parse(json); writer = new StringWriter(); jsonWriter = new JsonTextWriter(writer); jsonWriter.Formatting = Formatting.Indented; newJson = s.ToString(); Assert.AreEqual(@"{ ""type"": ""object"", ""additionalProperties"": { ""type"": ""string"" }, ""extends"": [ { ""type"": ""string"" }, { ""type"": ""object"" } ] }", newJson); }
public void GenerateSchemaSerializable() { JsonSchemaGenerator generator = new JsonSchemaGenerator(); DefaultContractResolver contractResolver = new DefaultContractResolver { IgnoreSerializableAttribute = false }; generator.ContractResolver = contractResolver; generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName; JsonSchema schema = generator.Generate(typeof(SerializableTestObject), true); string json = schema.ToString(); StringAssert.AreEqual( @"{ ""id"": ""Newtonsoft.Json.Tests.Schema.SerializableTestObject"", ""type"": [ ""object"", ""null"" ], ""additionalProperties"": false, ""properties"": { ""_name"": { ""required"": true, ""type"": [ ""string"", ""null"" ] } } }", json ); JTokenWriter jsonWriter = new JTokenWriter(); JsonSerializer serializer = new JsonSerializer(); serializer.ContractResolver = contractResolver; serializer.Serialize(jsonWriter, new SerializableTestObject { Name = "Name!" }); List <string> errors = new List <string>(); jsonWriter.Token.Validate(schema, (sender, args) => errors.Add(args.Message)); Assert.AreEqual(0, errors.Count); StringAssert.AreEqual( @"{ ""_name"": ""Name!"" }", jsonWriter.Token.ToString() ); SerializableTestObject c = jsonWriter.Token.ToObject <SerializableTestObject>( serializer ); Assert.AreEqual("Name!", c.Name); }
public void Extends() { string json; JsonSchemaResolver resolver = new JsonSchemaResolver(); json = @"{ ""id"":""first"", ""type"":""object"", ""additionalProperties"":{} }"; JsonSchema first = JsonSchema.Parse(json, resolver); json = @"{ ""id"":""second"", ""type"":""object"", ""extends"":{""$ref"":""first""}, ""additionalProperties"":{""type"":""string""} }"; JsonSchema second = JsonSchema.Parse(json, resolver); Assert.AreEqual(first, second.Extends[0]); json = @"{ ""id"":""third"", ""type"":""object"", ""extends"":{""$ref"":""second""}, ""additionalProperties"":false }"; JsonSchema third = JsonSchema.Parse(json, resolver); Assert.AreEqual(second, third.Extends[0]); Assert.AreEqual(first, third.Extends[0].Extends[0]); StringWriter writer = new StringWriter(); JsonTextWriter jsonWriter = new JsonTextWriter(writer); jsonWriter.Formatting = Formatting.Indented; third.WriteTo(jsonWriter, resolver); string writtenJson = writer.ToString(); Assert.AreEqual(@"{ ""id"": ""third"", ""type"": ""object"", ""additionalProperties"": false, ""extends"": { ""$ref"": ""second"" } }", writtenJson); StringWriter writer1 = new StringWriter(); JsonTextWriter jsonWriter1 = new JsonTextWriter(writer1); jsonWriter1.Formatting = Formatting.Indented; third.WriteTo(jsonWriter1); writtenJson = writer1.ToString(); Assert.AreEqual(@"{ ""id"": ""third"", ""type"": ""object"", ""additionalProperties"": false, ""extends"": { ""id"": ""second"", ""type"": ""object"", ""additionalProperties"": { ""type"": ""string"" }, ""extends"": { ""id"": ""first"", ""type"": ""object"", ""additionalProperties"": {} } } }", writtenJson); }
private TypeSchema Pop() { TypeSchema popped = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); TypeSchema newValue = _stack.LastOrDefault(); if (newValue != null) { _currentSchema = newValue.Schema; } else { _currentSchema = null; } return popped; }
public void JsonPropertyWithHandlingValues() { JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(); jsonSchemaGenerator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName; JsonSchema jsonSchema = jsonSchemaGenerator.Generate( typeof(JsonPropertyWithHandlingValues) ); string json = jsonSchema.ToString(); StringAssert.AreEqual( @"{ ""id"": ""Newtonsoft.Json.Tests.TestObjects.JsonPropertyWithHandlingValues"", ""required"": true, ""type"": [ ""object"", ""null"" ], ""properties"": { ""DefaultValueHandlingIgnoreProperty"": { ""type"": [ ""string"", ""null"" ], ""default"": ""Default!"" }, ""DefaultValueHandlingIncludeProperty"": { ""required"": true, ""type"": [ ""string"", ""null"" ], ""default"": ""Default!"" }, ""DefaultValueHandlingPopulateProperty"": { ""required"": true, ""type"": [ ""string"", ""null"" ], ""default"": ""Default!"" }, ""DefaultValueHandlingIgnoreAndPopulateProperty"": { ""type"": [ ""string"", ""null"" ], ""default"": ""Default!"" }, ""NullValueHandlingIgnoreProperty"": { ""type"": [ ""string"", ""null"" ] }, ""NullValueHandlingIncludeProperty"": { ""required"": true, ""type"": [ ""string"", ""null"" ] }, ""ReferenceLoopHandlingErrorProperty"": { ""$ref"": ""Newtonsoft.Json.Tests.TestObjects.JsonPropertyWithHandlingValues"" }, ""ReferenceLoopHandlingIgnoreProperty"": { ""$ref"": ""Newtonsoft.Json.Tests.TestObjects.JsonPropertyWithHandlingValues"" }, ""ReferenceLoopHandlingSerializeProperty"": { ""$ref"": ""Newtonsoft.Json.Tests.TestObjects.JsonPropertyWithHandlingValues"" } } }", json ); }
private void Push(TypeSchema typeSchema) { _currentSchema = typeSchema.Schema; _stack.Add(typeSchema); _resolver.LoadedSchemas.Add(typeSchema.Schema); }
public void SetUp() { this.JsonSchema = new JsonSchema(); }