Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft 7 with errors #13

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion JSON-Schema-Test-Suite
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
EXTENSION = postgres-json-schema
DATA = postgres-json-schema--0.1.1.sql
DATA = postgres-json-schema--0.1.1.sql postgres-json-schema--0.2.0.sql

# postgres build stuff
PG_CONFIG = pg_config
Expand Down
87 changes: 79 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ schemas](http://json-schema.org/) in PostgreSQL. It is implemented as a
PL/pgSQL function and you can use it as a check constraint to validate the
format of your JSON columns.

postgres-json-schema supports the entire JSON schema draft v4 spec, except for
postgres-json-schema supports the entire JSON schema draft v4 and v7 spec, except for
remote (http) references. It's tested against the official
[JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite).

Expand All @@ -17,14 +17,85 @@ postgres-json-schema is packaged as an PGXS extension. To install, just run
`make install` as root, then `CREATE EXTENSION "postgres-json-schema";` as the
database superuser.

# Usage

## Types
- `json_schema_validation_result` A composite type which contains error messages and path (an array to the path) within json data where the validation failed
#### contains the following attributes
- `path` a `text[]` to the path where the validation failed
- `error` the validation error message

## Functions

#### Functions accepting a argument `string_as_number` controlling whether a schema expecting a number may contain a valid number as a string. This is useful when dealing with for example python Decimal, which most implementations serialize it to json as a quoted string not to lose decimal precision.

- ```sql
-- Returns bool
validate_json_schema(schema jsonb, data jsonb, string_as_number bool)
```
- ```sql
-- Returns ARRAY json_schema_validation_result[]
get_json_schema_validations(schema jsonb, data jsonb, string_as_number bool)
```
- ```sql
-- Returns true if valid,
-- otherwise raises a check_constraint exception, this is useful when you want to get a detailed
-- error knowing which part of the json document failed to validate.
json_schema_check_constraint(
schema jsonb,
data jsonb,
string_as_number bool default false,
table_name text default '', -- if you need to set the value for TABLE in the PG_EXCEPTION_CONTEXT
column_name text default '' -- if you need to set the value for COLUMN in the PG_EXCEPTION_CONTEXT
)
```
- `json_schema_resolve_refs( schema )`

When dealing with a JSON schema that has `$id` uri values being used in `$ref`,
there is a convenient function to resolve those references
```sql
validate_json_schema( json_schema_resolve_refs( schema ), data );
-- or
json_schema_check_constraint( json_schema_resolve_refs( schema ), data, ... );
```


# Example

CREATE TABLE example (id serial PRIMARY KEY, data jsonb);
ALTER TABLE example ADD CONSTRAINT data_is_valid CHECK (validate_json_schema('{"type": "object"}', data));
#### Using standard default check constraint with boolean function
```sql
CREATE TABLE example (id serial PRIMARY KEY, data jsonb);
ALTER TABLE example ADD CONSTRAINT data_is_valid CHECK (validate_json_schema('{"type": "object"}', data));

INSERT INTO example (data) VALUES ('{}');
-- INSERT 0 1

INSERT INTO example (data) VALUES ('1');
-- ERROR: new row for relation "example" violates check constraint "data_is_valid"
-- DETAIL: Failing row contains (2, 1).
```


#### Using custom check constraint exception with detailed error
```sql
CREATE TABLE example (id serial PRIMARY KEY, data jsonb);
ALTER TABLE example ADD CONSTRAINT data_is_valid CHECK (json_schema_check_constraint('{"type": "object", "properties": { "foo": {"type": "number"}, "bar": { "prefixItems": [{ "type": "number" }, { "type": "number", "minimum": 2 }] } }}', data, true, table_name := 'example', column_name := 'data'));

INSERT INTO example (data) VALUES ('{}');
-- INSERT 0 1

INSERT INTO example (data) VALUES ('1');
-- ERROR: json_schema_validation_failed
-- DETAIL: [{"path": [], "error": "number is not a valid type: {object}"}]
-- CONTEXT: PL/pgSQL function json_schema_check_constraint(jsonb,jsonb,boolean,text,text) line 7 at RAISE

INSERT INTO example (data) VALUES ('{}');
-- INSERT 0 1
INSERT INTO example (data) VALUES ('{ "foo": "string" }');
-- ERROR: json_schema_validation_failed
-- DETAIL: [{"path": ["foo"], "error": "string is not a valid type: {number}"}]
-- CONTEXT: PL/pgSQL function json_schema_check_constraint(jsonb,jsonb,boolean,text,text) line 7 at RAISE

INSERT INTO example (data) VALUES ('1');
-- ERROR: new row for relation "example" violates check constraint "data_is_valid"
-- DETAIL: Failing row contains (2, 1).
INSERT INTO example (data) VALUES ('{ "foo": 1, "bar": ["a", 1.1] }');
-- ERROR: json_schema_validation_failed
-- DETAIL: [{"path": ["bar", "0"], "error": "string is not a valid type: {number}"}, {"path": ["bar", "1"], "error": "value must be >= 2"}]
-- CONTEXT: PL/pgSQL function json_schema_check_constraint(jsonb,jsonb,boolean,text,text) line 7 at RAISE
```
Loading