private void Push(JsonSchema value)
 {
     _currentSchema = value;
     _stack.Add(value);
     _resolver.LoadedSchemas.Add(value);
     _documentSchemas.Add(value.Location, value);
 }
        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;
        }
            public TypeSchema(Type type, JsonSchema schema)
            {
                ValidationUtils.ArgumentNotNull(type, "type");
                ValidationUtils.ArgumentNotNull(schema, "schema");

                Type = type;
                Schema = schema;
            }
            public TypeSchema(Type type, JsonSchema schema)
            {
                ValidationUtils.ArgumentNotNull(type, nameof(type));
                ValidationUtils.ArgumentNotNull(schema, nameof(schema));

                Type = type;
                Schema = schema;
            }
        private JsonSchema Pop()
        {
            JsonSchema poppedSchema = _currentSchema;
            _stack.RemoveAt(_stack.Count - 1);
            _currentSchema = _stack.LastOrDefault();

            return poppedSchema;
        }
        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);
        }
 private void ReferenceOrWriteSchema(JsonSchema schema)
 {
     if (schema.Id != null && _resolver.GetSchema(schema.Id) != null)
     {
         _writer.WriteStartObject();
         _writer.WritePropertyName(JsonSchemaConstants.ReferencePropertyName);
         _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);
            }
        }
 private void Push(TypeSchema typeSchema)
 {
     _currentSchema = typeSchema.Schema;
     _stack.Add(typeSchema);
     _resolver.LoadedSchemas.Add(typeSchema.Schema);
 }
 /// <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>
 /// <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)
 {
     bool valid = true;
     source.Validate(schema, (sender, args) => { valid = false; });
     return valid;
 }
        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);
        }
 public void AddAdditionalItems(JsonSchemaNode parentNode, JsonSchema schema)
 {
     parentNode.AdditionalItems = AddSchema(parentNode.AdditionalItems, schema);
 }
 public void AddAdditionalProperties(JsonSchemaNode parentNode, JsonSchema schema)
 {
     parentNode.AdditionalProperties = AddSchema(parentNode.AdditionalProperties, schema);
 }
        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 AddProperty(IDictionary<string, JsonSchemaNode> target, string propertyName, JsonSchema schema)
        {
            JsonSchemaNode propertyNode;
            target.TryGetValue(propertyName, out propertyNode);

            target[propertyName] = AddSchema(propertyNode, schema);
        }
        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();
        }
 public JsonSchemaNode Combine(JsonSchema schema)
 {
     return new JsonSchemaNode(this, 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>
 public static void Validate(this JToken source, JsonSchema schema)
 {
     source.Validate(schema, null);
 }
        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;
        }
        private JsonSchema ResolveReferences(JsonSchema schema)
        {
            if (schema.DeferredReference != null)
            {
                string reference = schema.DeferredReference;

                bool locationReference = (reference.StartsWith("#", StringComparison.OrdinalIgnoreCase));
                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;
        }
Exemple #24
0
 public JsonSchemaNode Combine(JsonSchema schema)
 {
     return(new JsonSchemaNode(this, 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(JsonSchemaConstants.ReferencePropertyName, 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();
        }
        /// <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())
                {
                }
            }
        }
        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();
        }