I am currently working on an API. The frontend that feeds the API uses GraphQL to send the requests to the server.
The frontend code does have a certain amount of validation, but since it is impossible to full secure a web client some of the validation needs to be repeated on the server. Anything that the client can do over https can be automated as an API. The client code used by the user contains all the information needed to do this!
Given that I have been receiving a json document it would be useful to have one central place to describe what is expected to be sent. This is where JSON Schemas come in.
The obvious starting point is https://json-schema.org/
This ends up with a document that looks something like:
{
"$schema": "http://json-schema.org/schema",
"title": "My Schema",
"description": "Some description",
"required": [
"list_of_things",
"name",
"my_object"
],
"type": "object",
"properties": {
"list_of_things": {
"type": "array",
"items": {
"$ref": "#/$defs/thing"
}
},
"name": {
"type": "string"
},
"my_object": {
"$ref": "#/$defs/my_object"
},
"age": {
"type": "integer"
}
},
"$defs": {
"thing": {
"type": "object",
"required": [
"lines",
"postcode"
],
"properties": {
"lines": {
"type": "array",
"items": {
"type": "string"
}
},
"postcode": {
"type": "string"
}
}
},
"my_object": {
"type": "object",
"required": [],
"properties": {
"length": {"type": "integer"}
}
}
}
Once you have that you can use https://hex.pm/packages/ex_json_schema to use this to create a validator for the json obect.
schema =
File.read!("myschema.json")
|> Jason.decode!()
|> ExJsonSchema.Schema.resolve()
ExJsonSchema.Validator.validate(schema, %{"foo" => "bar"}
# Returns this:
{:error,
[
{"Required properties list_of_things, name, my_object were not present.",
"#"}
]}
The practical use is that you get a description of what is wrong with the document and an idea of where in the document the error is.
In terms of validation this is a good start. You can find out missing fields and fields of a wrong type.
I have yet to make it handle smarter validations (such as only one item in the list can have the main boolean set).