예제 #1
0
        /// <summary>
        /// Downloads and registers a schema at the specified URI.
        /// </summary>
        public static IJsonSchema Get(string uri)
        {
            IJsonSchema schema;

            lock (_schemaLookup)
            {
                uri = uri.TrimEnd('#');
                if (!_schemaLookup.TryGetValue(uri, out schema))
                {
                    var schemaJson  = JsonSchemaOptions.Download(uri);
                    var schemaValue = JsonValue.Parse(schemaJson);
                    schema = JsonSchemaFactory.FromJson(schemaValue, new Uri(uri));

                    var metaSchemas = new IJsonSchema[]
                    {
                        JsonSchema07.MetaSchema,
                        JsonSchema06.MetaSchema,
                        JsonSchema04.MetaSchema
                    };

                    SchemaValidationResults validation = null;
                    if (schema.Schema != null)
                    {
                        var bySchema = metaSchemas.FirstOrDefault(s => s.Id == schema.Schema);
                        if (bySchema != null)
                        {
                            validation = bySchema.Validate(schemaValue);
                        }
                    }
                    else
                    {
                        foreach (var metaSchema in metaSchemas)
                        {
                            validation = metaSchema.Validate(schemaValue);
                            if (validation.Valid)
                            {
                                break;
                            }
                        }
                    }

                    if (validation != null && !validation.Valid)
                    {
                        var errors = string.Join(Environment.NewLine, validation.Errors.Select(e => e.Message));
                        throw new ArgumentException($"The given path does not contain a valid schema.  Errors: \n{errors}");
                    }

                    _schemaLookup[uri] = schema;
                }
            }

            return(schema);
        }
예제 #2
0
 /// <summary>
 /// Builds an object from a <see cref="JsonValue"/>.
 /// </summary>
 /// <param name="json">The <see cref="JsonValue"/> representation of the object.</param>
 /// <param name="serializer">The <see cref="JsonSerializer"/> instance to use for additional
 /// serialization of values.</param>
 public void FromJson(JsonValue json, JsonSerializer serializer)
 {
     if (json.Type == JsonValueType.Boolean)
     {
         if (json.Boolean)
         {
             Definition = JsonSchema04.Empty;
         }
     }
     else
     {
         Definition = JsonSchemaFactory.FromJson(json);
     }
 }
        // TODO: This is a JSON pointer.  Since JsonPatch uses it, it might be beneficial to implement as an object or at least reuse this.
        private IJsonSchema _ResolveLocalReference(JsonValue root, string path, Uri documentPath)
        {
            var properties = path.Split('/').Skip(1).ToList();

            if (!properties.Any())
            {
                return(JsonSchemaFactory.FromJson(root, _schemaFactory, documentPath));
            }
            var value = root;

            foreach (var property in properties)
            {
                var unescaped = _Unescape(property);
                if (value.Type == JsonValueType.Object)
                {
                    if (!value.Object.ContainsKey(unescaped))
                    {
                        return(null);
                    }
                    JsonValue id;
                    // There's not really another way to do this well without the reference knowing what
                    // version schema it should be using at each step in the path, so we test for both.
                    // Since draft-06's '$id' is less likely to be used as a regular JSON property, we
                    // check it first.
                    if (value.Object.TryGetValue("$id", out id) || value.Object.TryGetValue("id", out id))
                    {
                        documentPath = Uri.TryCreate(id.String, UriKind.Absolute, out Uri uri)
                                                                       ? uri
                                                                       : new Uri(documentPath, id.String);
                    }
                    value = value.Object[unescaped];
                }
                else if (value.Type == JsonValueType.Array)
                {
                    if (!int.TryParse(unescaped, out int index) || index >= value.Array.Count)
                    {
                        return(null);
                    }
                    value = value.Array[index];
                }
            }
            return(JsonSchemaFactory.FromJson(value, _schemaFactory, documentPath));
        }
예제 #4
0
        /// <summary>
        /// Builds an object from a <see cref="JsonValue"/>.
        /// </summary>
        /// <param name="json">The <see cref="JsonValue"/> representation of the object.</param>
        /// <param name="serializer">The <see cref="JsonSerializer"/> instance to use for additional serialization of values.</param>
        public virtual void FromJson(JsonValue json, JsonSerializer serializer)
        {
            var obj = json.Object;

            Id = obj.TryGetString("id");
            var uriFolder = DocumentPath?.OriginalString.EndsWith("/") ?? true ? DocumentPath : DocumentPath?.GetParentUri();

            if (!string.IsNullOrWhiteSpace(Id) &&
                (Uri.TryCreate(Id, UriKind.Absolute, out Uri uri) || Uri.TryCreate(uriFolder + Id, UriKind.Absolute, out uri)))
            {
                DocumentPath = uri;
                JsonSchemaRegistry.Register(this);
            }
            Schema      = obj.TryGetString("$schema");
            Title       = obj.TryGetString("title");
            Description = obj.TryGetString("description");
            if (obj.ContainsKey("default"))
            {
                Default = obj["default"];
            }
            MultipleOf       = obj.TryGetNumber("multipleOf");
            Maximum          = obj.TryGetNumber("maximum");
            ExclusiveMaximum = obj.TryGetBoolean("exclusiveMaximum");
            Minimum          = obj.TryGetNumber("minimum");
            ExclusiveMinimum = obj.TryGetBoolean("exclusiveMinimum");
            MaxLength        = (uint?)obj.TryGetNumber("maxLength");
            MinLength        = (uint?)obj.TryGetNumber("minLength");
            Pattern          = obj.TryGetString("pattern");
            if (obj.ContainsKey("additionalItems"))
            {
                if (obj["additionalItems"].Type == JsonValueType.Boolean)
                {
                    AdditionalItems = obj["additionalItems"].Boolean ? AdditionalItems.True : AdditionalItems.False;
                }
                else
                {
                    AdditionalItems = new AdditionalItems {
                        Definition = _ReadSchema(obj["additionalItems"])
                    }
                };
            }
            MaxItems = (uint?)obj.TryGetNumber("maxItems");
            MinItems = (uint?)obj.TryGetNumber("minItems");
            if (obj.ContainsKey("items"))
            {
                Items = JsonSchemaFactory.FromJson(obj["items"], DocumentPath);
            }
            UniqueItems   = obj.TryGetBoolean("uniqueItems");
            MaxProperties = (uint?)obj.TryGetNumber("maxProperties");
            MinProperties = (uint?)obj.TryGetNumber("minProperties");
            if (obj.ContainsKey("properties"))
            {
                Properties = obj["properties"].Object.ToDictionary(kvp => kvp.Key, kvp => _ReadSchema(kvp.Value));
            }
            Required = obj.TryGetArray("required")?.Select(jv => jv.String).ToList();
            if (obj.ContainsKey("additionalProperties"))
            {
                if (obj["additionalProperties"].Type == JsonValueType.Boolean)
                {
                    AdditionalProperties = obj["additionalProperties"].Boolean ? AdditionalProperties.True : AdditionalProperties.False;
                }
                else
                {
                    AdditionalProperties = new AdditionalProperties {
                        Definition = _ReadSchema(obj["additionalProperties"])
                    }
                };
            }
            if (obj.ContainsKey("definitions"))
            {
                Definitions = obj["definitions"].Object.ToDictionary(kvp => kvp.Key, kvp => _ReadSchema(kvp.Value));
            }
            if (obj.ContainsKey("patternProperties"))
            {
                var patterns = obj["patternProperties"].Object;
                PatternProperties = patterns.ToDictionary(kvp => new Regex(kvp.Key), kvp => _ReadSchema(kvp.Value));
            }
            if (obj.ContainsKey("dependencies"))
            {
                Dependencies = obj["dependencies"].Object.Select(v =>
                {
                    IJsonSchemaDependency dependency;
                    switch (v.Value.Type)
                    {
                    case JsonValueType.Object:
                        dependency = new SchemaDependency(v.Key, _ReadSchema(v.Value));
                        break;

                    case JsonValueType.Array:
                        if (!v.Value.Array.Any())
                        {
                            throw new ArgumentException("Property dependency must declare at least one property.");
                        }
                        dependency = new PropertyDependency(v.Key, v.Value.Array.Select(jv => jv.String));
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                    return(dependency);
                });
            }
            if (obj.ContainsKey("enum"))
            {
                Enum = json.Object["enum"].Array.Select(jv => new EnumSchemaValue(jv));
            }
            if (obj.ContainsKey("type"))
            {
                Type = obj["type"].FromJson();
            }
            if (obj.ContainsKey("allOf"))
            {
                AllOf = obj["allOf"].Array.Select(_ReadSchema);
            }
            if (obj.ContainsKey("anyOf"))
            {
                AnyOf = json.Object["anyOf"].Array.Select(_ReadSchema);
            }
            if (obj.ContainsKey("oneOf"))
            {
                OneOf = obj["oneOf"].Array.Select(_ReadSchema);
            }
            if (obj.ContainsKey("not"))
            {
                Not = _ReadSchema(obj["not"]);
            }
            var formatKey = obj.TryGetString("format");

            Format = StringFormat.GetFormat(formatKey);
            var details = obj.Where(kvp => !_definedProperties.Contains(kvp.Key)).ToJson();

            if (details.Any())
            {
                ExtraneousDetails = details;
            }
        }
예제 #5
0
 private IJsonSchema _ReadSchema(JsonValue json)
 {
     return(JsonSchemaFactory.FromJson <JsonSchema04>(json, DocumentPath));
 }
예제 #6
0
 private IJsonSchema _ReadSchema(JsonValue json)
 {
     return(JsonSchemaFactory.FromJson(json, () => new JsonSchema06(), DocumentPath));
 }
 /// <summary>
 /// Builds an object from a <see cref="JsonValue"/>.
 /// </summary>
 /// <param name="json">The <see cref="JsonValue"/> representation of the object.</param>
 /// <param name="serializer">The <see cref="JsonSerializer"/> instance to use for additional
 /// serialization of values.</param>
 public void FromJson(JsonValue json, JsonSerializer serializer)
 {
     AddRange(json.Array.Select(j => JsonSchemaFactory.FromJson(j, DocumentPath)));
 }