// JSON Schema types and definitions
///|
pub trait Validatable {
fn validate(
Self,
Json,
resolver~ : Resolver,
json_path~ : JsonPointer,
schema_path~ : JsonPointer,
) -> Array[ValidationError]
}
///|
/// JsonSchema
pub enum JsonSchema {
Any(AnySchema)
Null(NullSchema)
Boolean(BooleanSchema)
String(StringSchema)
Number(NumberSchema)
Integer(IntegerSchema)
Array(ArraySchema)
Object(ObjectSchema)
AnyOf(AnyOfSchema)
AllOf(AllOfSchema)
OneOf(OneOfSchema)
Ref(RefSchema)
Enum(EnumSchema)
Const(ConstSchema)
// Not(JsonSchema)
// If(Schema, Schema?, Schema?) // if, then, else
} derive(Debug, Eq)
///|
pub impl Validatable for JsonSchema with fn validate(
self,
value,
resolver~,
json_path~,
schema_path~,
) {
match self {
Const(s) => s.validate(value, resolver~, json_path~, schema_path~)
Integer(s) => s.validate(value, resolver~, json_path~, schema_path~)
Enum(s) => s.validate(value, resolver~, json_path~, schema_path~)
Boolean(s) => s.validate(value, resolver~, json_path~, schema_path~)
Ref(s) => s.validate(value, resolver~, json_path~, schema_path~)
Null(s) => s.validate(value, resolver~, json_path~, schema_path~)
Any(s) => s.validate(value, resolver~, json_path~, schema_path~)
Number(c) => c.validate(value, resolver~, json_path~, schema_path~)
String(c) => c.validate(value, resolver~, json_path~, schema_path~)
Array(c) => c.validate(value, resolver~, json_path~, schema_path~)
Object(v) => v.validate(value, resolver~, json_path~, schema_path~)
AllOf(s) => s.validate(value, resolver~, json_path~, schema_path~)
OneOf(s) => s.validate(value, resolver~, json_path~, schema_path~)
AnyOf(s) => s.validate(value, resolver~, json_path~, schema_path~)
// WIP
// Not(_schema) =>
// // TODO: implement Not validation
// []
}
}
///|
pub impl @json.FromJson for JsonSchema with fn from_json(
json : Json,
json_path : @json.JsonPath,
) -> JsonSchema raise {
guard json is Json::Object(obj) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
match obj {
{ "type": "any", .. } =>
AnySchema::from_json(json, json_path) |> JsonSchema::Any
{ "const": value, .. } => Const({ value, })
{ "$ref": String(refstr), .. } => {
let pointer = JsonPointer::from_string(refstr).unwrap()
JsonSchema::Ref(RefSchema::{ pointer, })
}
{ "type": "object", .. } =>
ObjectSchema::from_json(json, json_path) |> JsonSchema::Object
{ "type": "array", .. } =>
ArraySchema::from_json(json, json_path) |> JsonSchema::Array
{ "type": "null", .. } => JsonSchema::Null(NullSchema::{ })
{ "type": "boolean", .. } => JsonSchema::Boolean(BooleanSchema::{ })
{ "type": "string", .. } =>
StringSchema::from_json(json, json_path) |> JsonSchema::String
{ "type": "number", .. } =>
NumberSchema::from_json(json, json_path) |> JsonSchema::Number
{ "type": "integer", .. } =>
IntegerSchema::from_json(json, json_path) |> JsonSchema::Integer
{ "anyOf": Array(schemas), .. } =>
JsonSchema::AnyOf({
schemas: schemas.map(s => {
@json.from_json(s, path=json_path.add_key("anyOf"))
}),
})
{ "allOf": Array(schemas), .. } =>
JsonSchema::AllOf({
schemas: schemas.map(s => {
@json.from_json(s, path=json_path.add_key("allOf"))
}),
})
{ "oneOf": Array(schemas), .. } =>
JsonSchema::OneOf({
schemas: schemas.mapi((i, s) => {
@json.from_json(s, path=json_path.add_key("oneOf").add_index(i))
}),
parsed_enumerable: None,
parsed_nullable: None,
})
// JsonSchema::Not(@json.from_json(schema, path=json_path.add_key("not")))
{ "enum": Array(values), .. } => JsonSchema::Enum(EnumSchema::{ values, })
_ => JsonSchema::Any(AnySchema::{ })
}
}
///| Primitive types
///|
pub struct AnySchema {} derive(Debug, Eq, FromJson, ToJson)
///|
impl Validatable for AnySchema with fn validate(
_self,
_value,
resolver~,
json_path~,
schema_path~,
) {
ignore((json_path, schema_path, resolver))
[]
}
///|
pub struct NullSchema {} derive(Debug, Eq, FromJson, ToJson)
///|
impl Validatable for NullSchema with fn validate(
_self,
value,
resolver~,
json_path~,
schema_path~,
) {
ignore((json_path, schema_path, resolver))
match value {
Null => []
_ =>
[ValidationError::new(value, json_path, schema_path, "Value is not null")]
}
// []
}
///|
pub struct BooleanSchema {} derive(Debug, Eq, FromJson, ToJson)
///|
impl Validatable for BooleanSchema with fn validate(
_self,
value,
resolver~,
json_path~,
schema_path~,
) {
ignore((json_path, schema_path, resolver))
match value {
True => []
False => []
_ =>
[
ValidationError::new(
value, json_path, schema_path, "Value is not a boolean",
),
]
}
}