Coder Social home page Coder Social logo

for-get / jesse Goto Github PK

View Code? Open in Web Editor NEW
117.0 11.0 62.0 7.11 MB

jesse (JSon Schema Erlang) is an implementation of a JSON Schema validator for Erlang.

Home Page: https://github.com/for-get/jesse

License: Apache License 2.0

Makefile 1.76% Erlang 97.93% Emacs Lisp 0.06% Python 0.01% Dockerfile 0.19% Shell 0.05%
json-schema erlang

jesse's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jesse's Issues

Missing tag for 1.5.0 release

I noticed that although 1.5.0 release is mentioned almost in the changelog a year ago the corresponding tag is missing

Some strange problem with nested references

I tried to minimize test case, but still not sure if it's minimal enough:

-module(jesse_test).

-export([test/0]).

test() ->
    Schema1 =
        #{<<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
          <<"definitions">> =>
              #{<<"my_local_ref">> => #{
                  <<"properties">> => #{
                     <<"my_prop">> => #{
                       <<"$ref">> => <<"schema2#definitions/my_remote_ref">>
                      }
                    }
                 }},
          <<"properties">> => #{
            <<"my_list">> =>
                #{<<"items">> =>
                      #{<<"$ref">> => <<"#definitions/my_local_ref">>}}}},
    Schema2 =
        #{<<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
          <<"definitions">> =>
              #{<<"my_remote_ref">> => #{}}},
    JSON = #{<<"my_list">> => [#{<<"my_prop">> => null},
                               #{<<"my_prop">> => null}]},
    jesse:add_schema("schema1", Schema1),
    jesse:add_schema("schema2", Schema2),

    io:format("~s~n~s~n~s~n", [jiffy:encode(J, [pretty]) || J <- [Schema1, Schema2, JSON]]),
    jesse:validate("schema1", JSON).
> jesse_test:test().
{
  "properties" : {
    "my_list" : {
      "items" : {
        "$ref" : "#definitions/my_local_ref"
      }
    }
  },
  "definitions" : {
    "my_local_ref" : {
      "properties" : {
        "my_prop" : {
          "$ref" : "schema2#definitions/my_remote_ref"
        }
      }
    }
  },
  "$schema" : "http://json-schema.org/draft-04/schema#"
}
{
  "definitions" : {
    "my_remote_ref" : {

    }
  },
  "$schema" : "http://json-schema.org/draft-04/schema#"
}
{
  "my_list" : [
    {
      "my_prop" : null
    },
    {
      "my_prop" : null
    }
  ]
}
{error,[{schema_invalid,#{<<"properties">> => #{<<"my_prop">> => #{<<"$ref">> => <<"schema2#definitions/my_remote_ref">>}}},
                        schema_invalid}]}

It says 'schema invalid', while it's ok.

Here are part of tracer output. Maybe it can help somehow

dbg:tracer(), dbg:tpl(jesse_state, []), dbg:tpl(jesse_error, []), dbg:tpl(jesse_schema_validator, []), dbg:p(spawn_link(fun() -> timer:sleep(1), exit(jesse_test:test()) end), [c, m]).

(<0.18340.0>) call jesse_schema_validator:select_and_run_validator(<<"http://json-schema.org/draft-04/schema#">>,#{<<"$ref">> => <<"#definitions/my_local_ref">>},#{<<"my_prop">> => null},{state,#{<<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
         <<"definitions">> => #{<<"my_remote_ref">> => #{}}},
       #{<<"properties">> => #{<<"my_prop">> => #{<<"$ref">> => <<"schema2#definitions/my_remote_ref">>}}},
       [1,<<"my_list">>],
       0,[],#Fun<jesse_error.default_error_handler.3>,
       <<"http://json-schema.org/draft-04/schema#">>,
       #Fun<jesse_database.read.1>,<<"schema2">>})
(<0.18340.0>) call jesse_state:resolve_reference({state,#{<<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
         <<"definitions">> => #{<<"my_remote_ref">> => #{}}},
       #{<<"properties">> => #{<<"my_prop">> => #{<<"$ref">> => <<"schema2#definitions/my_remote_ref">>}}},
       [1,<<"my_list">>],
       0,[],#Fun<jesse_error.default_error_handler.3>,
       <<"http://json-schema.org/draft-04/schema#">>,
       #Fun<jesse_database.read.1>,<<"schema2">>},<<"#definitions/my_local_ref">>)
(<0.18340.0>) call jesse_state:combine_id(<<"schema2">>,<<"#definitions/my_local_ref">>)
(<0.18340.0>) call jesse_state:combine_relative_id(<<"schema2">>,"#definitions/my_local_ref")
(<0.18340.0>) call jesse_state:find_schema({state,#{<<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
         <<"definitions">> => #{<<"my_remote_ref">> => #{}}},
       #{<<"properties">> => #{<<"my_prop">> => #{<<"$ref">> => <<"schema2#definitions/my_remote_ref">>}}},
       [1,<<"my_list">>],
       0,[],#Fun<jesse_error.default_error_handler.3>,
       <<"http://json-schema.org/draft-04/schema#">>,
       #Fun<jesse_database.read.1>,<<"schema2">>},<<"schema2">>)
(<0.18340.0>) call jesse_state:find_schema({state,#{<<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
         <<"definitions">> => #{<<"my_remote_ref">> => #{}}},
       #{<<"properties">> => #{<<"my_prop">> => #{<<"$ref">> => <<"schema2#definitions/my_remote_ref">>}}},
       [1,<<"my_list">>],
       0,[],#Fun<jesse_error.default_error_handler.3>,
       <<"http://json-schema.org/draft-04/schema#">>,
       #Fun<jesse_database.read.1>,<<"schema2">>},"schema2")
(<0.18340.0>) call jesse_state:local_schema(#{<<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
  <<"definitions">> => #{<<"my_remote_ref">> => #{}}},[<<"definitions">>,<<"my_local_ref">>])
(<0.18340.0>) call jesse_state:local_schema(#{<<"my_remote_ref">> => #{}},[<<"my_local_ref">>])
(<0.18340.0>) call jesse_state:local_schema(not_found,[])
(<0.18340.0>) call jesse_error:handle_schema_invalid(schema_invalid,{state,#{<<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
         <<"definitions">> => #{<<"my_remote_ref">> => #{}}},
       #{<<"properties">> => #{<<"my_prop">> => #{<<"$ref">> => <<"schema2#definitions/my_remote_ref">>}}},
       [1,<<"my_list">>],
       0,[],#Fun<jesse_error.default_error_handler.3>,
       <<"http://json-schema.org/draft-04/schema#">>,
       #Fun<jesse_database.read.1>,<<"schema2">>})
(<0.18340.0>) call jesse_state:get_current_schema({state,#{<<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
         <<"definitions">> => #{<<"my_remote_ref">> => #{}}},
       #{<<"properties">> => #{<<"my_prop">> => #{<<"$ref">> => <<"schema2#definitions/my_remote_ref">>}}},
       [1,<<"my_list">>],
       0,[],#Fun<jesse_error.default_error_handler.3>,
       <<"http://json-schema.org/draft-04/schema#">>,
       #Fun<jesse_database.read.1>,<<"schema2">>})
(<0.18340.0>) call jesse_error:handle_error({schema_invalid,#{<<"properties">> => #{<<"my_prop">> => #{<<"$ref">> => <<"schema2#definitions/my_remote_ref">>}}},
                schema_invalid},{state,#{<<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
         <<"definitions">> => #{<<"my_remote_ref">> => #{}}},
       #{<<"properties">> => #{<<"my_prop">> => #{<<"$ref">> => <<"schema2#definitions/my_remote_ref">>}}},
       [1,<<"my_list">>],
       0,[],#Fun<jesse_error.default_error_handler.3>,
       <<"http://json-schema.org/draft-04/schema#">>,
       #Fun<jesse_database.read.1>,<<"schema2">>})

Jesse's database depends on the CWD => changing it breaks jesse

It seems that starting from 820d0e9#diff-06b055de1c1c5e19892ec0ef0a7d057f, jesse stores schemas in its database using canonical keys, which, unfortunately, depend on the current working directory (see

"file://" ++ filename:join(raw_canonical_path(filename:absname(Path))).
and https://github.com/erlang/otp/blob/05dce0f330c83278cb134c7235a5353ce4116307/lib/stdlib/src/filename.erl#L73).

In particular, that means this:

1> jesse:add_schema(key, {[]}).       
ok
2> jesse:validate(key, {[]}).
{ok,{[]}}
3> file:set_cwd("/").        
ok
4> jesse:validate(key, {[]}).
{error,{database_error,"file:///key",schema_not_found}}

which I think should be regarded as a bug?

Two questions here:

  1. do you guys see this behaviour as a bug too? (if not, why?)
  2. I'd be very happy to offer a patch, but since I'm not sure I get the rationale behind 820d0e9, I'd very much like some advice on how to go about this.

Thanks! :)

jesse does not fully respect internal references

draft-wright-json-schema-00 (Internet-Draft October 13, 2016) | 8.2.1. Internal references states that:

Schemas can be identified by any URI that has been given to them, including a JSON Pointer or their URI given directly by "id".

In particular, the following schema will not work with jesse:

{
    "id": "http://example.net/root.json",
    "items": {
        "type": "array",
        "items": { "$ref": "#item" }
    },
    "definitions": {
        "single": {
            "id": "#item",
            "type": "integer"
        }
    }
}

Failing example with internal reference URI given directly by "id" (#item):

1> jesse:add_schema("http://example.net/root.json", <<"{\"id\":\"http://example.net/root.json\",\"items\":{\"type\":\"array\",\"items\":{\"$ref\":\"#item\"}},\"definitions\":{\"single\":{\"id\":\"#item\",\"type\":\"integer\"}}}">>, [{parser_fun, fun jsx:decode/1}]).
ok
2> jesse:validate("http://example.net/root.json", <<"[[1, 2, 3]]">>, [{parser_fun, fun jsx:decode/1}]).
{error,[{schema_invalid,[{<<"$ref">>,<<"#item">>}],
                        schema_invalid}]}

Successful example with internal reference given as JSON Pointer (#/definitions/single):

1> jesse:add_schema("http://example.net/root.json", <<"{\"id\":\"http://example.net/root.json\",\"items\":{\"type\":\"array\",\"items\":{\"$ref\":\"#/definitions/single\"}},\"definitions\":{\"single\":{\"id\":\"#item\",\"type\":\"integer\"}}}">>, [{parser_fun, fun jsx:decode/1}]).
ok
2> jesse:validate("http://example.net/root.json", <<"[[1, 2, 3]]">>, [{parser_fun, fun jsx:decode/1}]).
{ok,[[1,2,3]]}

Tools SHOULD take note of the URIs that schemas, including subschemas, provide for themselves using "id". This is known as "Internal referencing".

So it is recommended by IETF to support URIs both for schemas (which jesse currently does) and subschemas (which is lacking).

Handle boolean type

We have an application which should be able to receive this type. We would like to handle this type as well.
A pull request has` been created: 0e07b0e

Please review and if you have any comments lets discuss it.

THX.

Tag 0.1.3 (from hex.pm) does not validate patternProperties?

Json example:

{
        "configs": {
                "ba117f6-e26c-4dca-83e6-d397d90889d4": {
                        "cpu": "a"
                 }
         }
}

Schema:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
        "configs": {
        "type": "object",
        "additionalProperties": false,
        "patternProperties": {
          "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$": {
            "type": "object",
            "properties": {
              "cpu": {
                "type": "string",
                "enum": ["a", "b"]
              }
          }
        }
      }
    }
  }
}

enum does not work as expected.

"pattern" and "patternProperties" do not support unicode properties

I have noticed that when putting regex patterns in pattern and patternProperties, \w does not match unicode letters (like ū, , п) as expected. You have to use [\p{L}\p{N}_] instead. It looks like this is because the patterns are not compiled/executed with the ucp in re:compile/2:

ucp

Specifies that Unicode character properties are to be used when resolving \B, \b, \D, \d, \S, \s, \W and \w. Without this flag, only ISO Latin-1 properties are used. Using Unicode properties hurts performance, but is semantically correct when working with Unicode characters beyond the ISO Latin-1 range.

Later it explains:

By default, in unicode mode, characters with values > 255, that is, all characters outside the ISO Latin-1 character set, never match \d, \s, or \w, and always match \D, \S, and \W. These sequences retain their original meanings from before UTF support was available, mainly for efficiency reasons. However, if option ucp is set, the behavior is changed so that Unicode properties are used to determine character types, as follows:

\d
Any character that \p{Nd} matches (decimal digit)
\s
Any character that \p{Z} or \h or \v
\w
Any character that matches \p{L} or \p{N} matches, plus underscore

Is this intended to not use this behavior? It seems unexpected to me (having this behavior off by default is not generally expected). Obviously I have a workaround just using the pattern I mentioned ([\p{L}\p{N}_]), so not a big deal if this isn't the behavior you all want.

Performance of validation of JSON objects with very long lists of JSON objects within is very, very slow.

It seems that validating an object with a list of 1000 objects with uniqueItems property takes time in the order of one second to complete.

This may be verified by creating an object such as:

{
  "test": [
    {"key1": "1", "key2": "1", "key3": "1", },
    {"key1": "2", "key2": "2", "key3": "3", },
    ...
    {"key1": "1000", "key2": "1000", "key3": "1000", },
  ]
}

and validating it against an schema such as:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "definitions": {
    "dataType": {
      "type": "object",
      "properties": {
          "key1": "string",
          "key2": "string",
          "key3": "string"
      }
    }
  },
  "type": "object",
  "properties": {
    "test": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "$ref": "#/definitions/dataType"
      }
    }
  }
}

Problem with "date-time" format validation

I have a problem with "format": "date-time" validation and it seems like a bug.

Value: <<"2017-04-12T23:20:50Z">>
Property: #{<<"format">> => <<"date-time">>, <<"type">> => <<"string">>},

Brief analysis shows that problem most likely here: https://github.com/for-GET/jesse/blob/master/src/jesse_validator_draft4.erl#L956
Instead of "State", check_format function returns boolean.

check_format(Value, _Format = <<"date-time">>, State) when is_binary(Value) ->
  try
    <<Date:10/bytes, $T, Time:8/bytes, $Z>> = Value,
    valid_date(Date) andalso valid_time(Time)
  catch
    error:{badmatch, _} -> handle_data_invalid(?wrong_format, Value, State)
  end;

Tests from upstream are 6 years old

Hi, when checking the testing from upstream (from test/JSON-Schema-Test-Suite/), I noticed that the tests that I think are used now are from 6 years ago, since the submodule commit has not changed.

Is this the case? Thanks.

list of objects with requred properties

Minimum schema:

{
  "items": {
    "required": ["b"]
  },
  "$schema": "http://json-schema.org/draft-04/schema#"
}

Minimum JSON

[{"c": "d"}]
jesse:validate_with_schema(#{<<"items">> => #{<<"required">> => [<<"b">>]},
                             <<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>},
                           [#{<<"c">> => <<"d">>}]).
{ok,[#{<<"c">> => <<"d">>}]}

Expected: '{missing_required_property, "b"}', but validation succeeds instead.

Other implementations (eg http://jsonschemalint.com/draft4/) catches this error.

allow non-schema keys alongside $ref

Since 1.5.0 or rather #54 this schema fails:

{
  "refs": {
    "not": {
      "type": "null"
    }
  },
  "$ref": "#refs/A"
}

with only_ref_allowed. Not sure how correct the implementation of https://www.jsonschemavalidator.net is but it says this is a valid draft04 schema.

Side note: I believe jesse's handling of not schemas is incorrect but I'll investigate more on that.

draft-06 / draft-07 support?

Hello from the JSON Schema spec project!

Does this project intend to add support for the recent drafts 6 and/or 7? I'm happy to answer any questions about the new (and forthcoming) drafts.
http://json-schema.org/specification.html

We will at some point be re-organizing the implementation lists to promote implementations supporting at least draft-06 and make draft-04-and-older-only implementations less visible.

Greatly expand the documentation around how $ref works

It is really really really really really super opaque, frustrating and annoying to figure out how $ref is supposed to work.

I think I'm too close to my emotions to write clearly and calmly about this, but I started a gist with some of my research notes. I'd eventually like to incorporate those notes in a cleaned up form into the documentation or README.

Is there an appetite to 👍 on a PR which simply attempts to see if the given $ref key matches any records in ETS before all the canonicalization happens?

Request release

Hi. Would you consider a Git tag and publish to Hex.pm for master? Thanks much.

improve types in jesse.erl

Port of klarna/jesse#10 by @andreineculau


 andreineculau 2 days ago 
I personally would have liked 1) the error to be more uniform 2) the errors to be categorized e.g.

-type error_reason() :: { 'schema_invalid'
                        , Schema :: json_term()
                        , Error :: schema_error()
                        }
                      | { 'data_invalid'
                        , Schema :: json_term()
                        , Error  :: data_error()
                        , Data   :: json_term()
                        }.

-type schema_error() :: {schema_error_id(), Details :: any() }
-type schema_error_id() :: 'missing_id_field'
                         | ...

-type data_error() :: {data_error_id(), Details :: any() }
-type data_error_id() :: 'missing_required_property'
                       | ...
Reason: improved/clearer documentation IMO, and cleaner pattern matching.

Just a thought, @Cy6erBr4in :) Nice effort

PS: the above is just to illustrate the pattern; the type definition (for Details) can be more explicit per *errorid and more documentation-driven

internal reference

I have file

{
    "title" : "login",
    "id" : "login.json#",
    "$schema" : "http://json-schema.org/draft-04/schema#",
    "type" : "object",
    "properties" : {
        "username" : {
            "type" : "string",
            "description" : "Username of the user"
        },
        "password" : {
            "type" : "string",
            "description" : "Plain password for user (security not defined as of now)"
        }
    },
    "required" : ["username", "password"]
}

and another file

{
    "title" : "Schema for session creation",
    "$schema" : "http://json-schema.org/draft-04/schema#",
    "id" : "session/put.json#",
    "type" : "object",
    "properties" : {
        "content" : {
            "type" : "object",
            "oneOf" : [
                {"$ref" : "login.json#"}
            ]
        }
    },
    "required" : ["content"]
}

both the above schemas are loaded jesse, but the $ref attribute is not resolved and waits for infinite time. Am I doing anything wrong? Should I try using scheme_loader_fun option?

anyOf validation failing if reference schema has additionalProperties property

{
    "title" : "Update Vehicle",
    "$schema" : "http://json-schema.org/draft-04/schema#",
    "id" : "post_vehicle.json",
    "type" : "object",
    "properties" : {
        "content" : {
            "type" : "object",
            "anyOf" : [
                {
                    "$ref" : "post_car.json"
                },
                {
                    "$ref" : "post_jet.json"
                }
            ]
        }
    },
    "required" : ["content"],
    "additionalProperties" : false
}

The post_car.json has the below

{
    "title" : "Update car",
    "$schema" : "http://json-schema.org/draft-04/schema#",
    "id" : "post_car.json",
    "type" : "object",
    "properties" : {
        "steering_type" : {
            "type" : "object",
            "properties" : .......
        }
...........
    },
    "additionalProperties" : false
}

The validation is failing with above and passing when I remove the below lines in post_car.json,

    "additionalProperties" : false

if I am right if the schema validation fails in post_car.json, it should process for post_jet.json, this behaviour is happening only when the above property "addtionalProperties" is present.

anyOf / OneOf returns unexpected error with allowed_errors=infinity

Might be caused by fix for #22

Minimized example:

data.json

{
  "unknown_field1":true,
  "known_field1":{
    "some_id":"410391-8351"
  },
  "known_field2":{
    "client_ip":"127.0.0.1"
  }
}

schema.json

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "additionalProperties": false,
    "properties": {
        "known_field2": {
            "additionalProperties": false,
            "properties": {
                "client_ip": {
                    "type": "string",
                    "anyOf": [
                        { "format": "ipv4" },
                        { "format": "ipv6" }
                    ]
                }
            }
        },
        "known_field1": {
            "additionalProperties": false,
            "properties": {
                "some_id": {
                    "anyOf": [
                        {
                            "pattern": "^[0-9]{6}[+-]?[0-9]{3}[0-9A-Z]{1}$"
                        },
                        {
                            "pattern": "^[8-9][0-9]{8}$"
                        },
                        {
                            "pattern": "^([0-9]{8}|[0-9]{6})[+-]?[0-9]{4}$"
                        }
                    ]
                }
            }
        }
    }
}
{ok, Data} = file:read_file("data.json"),
{ok, Schema} = file:read_file("schema.json"),
jesse:validate_with_schema(
      Schema,
      Data,
      [{allowed_errors,infinity}, {parser_fun, fun jsx:decode/1}]).
%-----
{error,[{data_invalid,[<...>],
                      no_extra_properties_allowed,
                      [{<<"unknown_field1">>,true},
                       {<<"known_field1">>,[{<<"some_id">>,<<"4103918351">>}]},
                       {<<"known_field2">>,[{<<"client_ip">>,<<"127.0.0.1">>}]}],
                      [<<"unknown_field1">>]},
        {data_invalid,[{<<"type">>,<<"string">>},
                       {<<"anyOf">>,
                        [[{<<"format">>,<<"ipv4">>}],[{<<"format">>,<<"ipv6">>}]]}],
                      any_schemas_not_valid,<<"127.0.0.1">>,
                      [<<"known_field2">>,<<"client_ip">>]},
        {data_invalid,[{<<"anyOf">>,
                        [[{<<"pattern">>,<<"^[0-9]{6}[+-]?[0-9]{3}[0-9A-Z]{1}$">>}],
                         [{<<"pattern">>,<<"^[8-9][0-9]{8}$">>}],
                         [{<<"pattern">>,
                           <<"^([0-9]{8}|[0-9]{6})[+-]?[0-9]{4}$">>}]]}],
                      any_schemas_not_valid,<<"410321-9202">>,
                      [<<"known_field1">>,<<"some_id">>]}]}

I expect it to only generate no_extra_properties_allowed, but it also generates any_schemas_not_valid

Move from Travis CI to GitHub Actions?

Would you be interested in a pull request that moves CI from Travis CI to GitHub Actions, or at least adds GitHub Actions alongside Travis CI? It seems travis-ci.org will stop being useful from Dec 31 2020. I can do it, except that I think you need to create the workflow yml, first, in master, after which I can branch off of.

Master add_schema broken

Last night (8th jan 2017) we did a build which clones the jesse repo and we pulled the latest master branch, which seems to be broken. From a quick review the order of parameters from jesse:add_schema/2 (which we call) into jesse_database seem to be incorrect, though I'm judging by variable name only, with no knowledge of internal workings.
Last fridays (6th jan 2017) master version was working fine.

make a release?

jesse build will fail on some configuration using erlang OTP 21. Having a release including the last commit would work.

Errors returned are different depending on options used

With jesse 1.4.0, I'm having trouble using the options [] and [{allowed_errors, 1}], because yields different results. For example, consider the following example document:

{
    "data": {
        "type": "document",
        "id": 1
    }
}

where /data/id should be "1" and not 1 and the schema from http://jsonapi.org/schema

The problem is that using [] or [{allowed_errors, 0}] yields a different error than [{allowed_errors, 1}]. Because of that there is no single API call that would always yield the same error first (i.e. one has to first validate and get an error, then validate again with allowed errors set to 1 to get the specific error).

Maybe I'm misunderstanding how jesse operates, but for the above document and schema using infinity yields a lot of errors for all the branches of the schema (although the document is correct).

Is there a canonical way to validate the document successfully (because it is valid) and get the most specific error first?

Expected

Using [{allowed_errors, 1}] we get:

34> jesse:validate(jsonapi, #{<<"data">> => #{<<"type">> => <<"user">>, <<"id">> => 1}}).
{error,[{data_invalid,#{<<"type">> => <<"string">>},
                      wrong_type,1,
                      [<<"data">>,<<"id">>]}]}

Actual

Using no options, we get not_one_schema_valid as the first error, where one would expect the most specific error first (as with allowing only 1 error).

1> jesse:validate(jsonapi, #{<<"data">> => #{<<"type">> => <<"user">>, <<"id">> => 1}}).
{error,[{data_invalid,#{...schema redacted...},
                      not_one_schema_valid,
                      #{<<"data">> => #{<<"id">> => 1,<<"type">> => <<"user">>}},
                      []}]}

Default schema loader fun with file and http/s support

I don't know if this is legacy (jesse not supporting $ref in the beginning) but i have a commit that adds loading (and adding to internal storage) referenced schemas given a start schema with an id using the file: or http: URI scheme.

This works brilliantly for the CLI version.

Ping @Cy6erBr4in

jesse:load_schema/2 question

I have my schemas in priv/schema which I am loading by

Path = code:application(foo) ++ "/schema",
jesse:load_schemas(Path, fun(D) -> jiffy:decode(D, [return_maps]) end).

Later, I want to reference these loaded schemas by the ids embedded in the schemas themselves, but it appears the only way they're stored is using absolute paths on my local disk.

Example:

{
  "$id": "http://example.com/schema/foo.json",
}

Later I want to

jesse:validate("http://example.com/schema/foo.json", InputJSON)

but of course it says there's no schema named that. It seems like jesse attempts to locate the id attribute in a schema - does it just ignore it?

oneOf doesn't fail when nested in a list?

Schema = jiffy:decode(F, [return_maps]).                                                                       
#{<<"additionalProperties">> => false,
  <<"minProperties">> => 1,
  <<"patternProperties">> =>
      #{<<"^[a-zA-Z]{1}[a-zA-Z0-9_]{2,}$">> =>
            #{<<"oneOf">> =>
                  [#{<<"type">> => <<"number">>},
                   #{<<"type">> => <<"string">>},
                   #{<<"type">> => <<"boolean">>},
                   #{<<"type">> => <<"null">>},
                   #{<<"items">> =>
                         #{<<"oneOf">> =>
                               [#{<<"type">> => <<"number">>},
                                #{<<"type">> => <<"string">>},
                                #{<<"type">> => <<"boolean">>}]},
                     <<"type">> => <<"array">>}]}}}
27> Body1 = #{ <<"key1">> => 9, <<"albatross">> => <<"value1">>, <<"list">> => [true, 1, [<<"something">>, null]]}.
#{<<"albatross">> => <<"value1">>,<<"key1">> => 9,
  <<"list">> => [true,1,[<<"something">>,null]]}

Expected result: a list value with a list inside of it should fail oneOf validation as defined above.

Actual result:

28> jesse:validate_with_schema(Schema, Body1).                                                                     
{ok,#{<<"albatross">> => <<"value1">>,<<"key1">> => 9,
      <<"list">> => [true,1,[<<"something">>,null]]}}

I don't understand why?

Need some advise for a new JSON schema validator

I am the developer of ejsv. I needed a JSON schema validation library that could easily be extended and shared logic where possible, and I read through Jesse and found it very difficult in that regard. I am not familar with JSON schema, but I like my Erlang work 🤣

So I managed to achieve the requirement by implementing an abstraction between the keyword rules and the assertions themselves, but I failed to think about $ref's 💩

I was thinking I needed a more fine grained API in ejsv_cache, what might you recommend? The code is quite simple to read through (I hope) and I would really appreciate your thoughts otherwise!

default_schema_ver not working as documented

Clarifying up the side note I had in #62:

To specify which validator to use by default (if there's no $schema property in
the given schema), one should use 'default_schema_ver' option when call
`jesse:validate/3` or `jesse:validate_with_schema/3`, the value should be
a binary consisting a schema path,
 i.e. <<"http://json-schema.org/draft-03/schema#">>.

When $schema is specified, the value of default_schema_ver is used regardless.
not is valid in draft3 but not draft4.

jesse:validate_with_schema(#{<<"$schema">> => <<"http://json-schema.org/draft-03/schema#">>, <<"components">> => #{<<"schemas">> => #{<<"A">> => #{<<"not">> => #{<<"type">> => <<"null">>}}}}, <<"$ref">> => <<"#/components/schemas/A">>}, <<"wef">>, [{allowed_errors,infinity}, {default_schema_ver,<<"http://json-schema.org/draft-04/schema#">>}]).
{error,[{data_invalid,#{<<"not">> =>
                            #{<<"type">> => <<"null">>}},
                      not_schema_valid,<<"wef">>,[]}]}

With default set to 03 instead of 04 the not is correctly checked:

jesse:validate_with_schema(#{<<"$schema">> => <<"http://json-schema.org/draft-03/schema#">>, <<"components">> => #{<<"schemas">> => #{<<"A">> => #{<<"not">> => #{<<"type">> => <<"null">>}}}}, <<"$ref">> => <<"#/components/schemas/A">>}, <<"wef">>, [{allowed_errors,infinity}, {default_schema_ver,<<"http://json-schema.org/draft-03/schema#">>}]).
{ok,<<"wef">>}

Maybe incorrect validation result

Hello!

Trying to validate this json:

{
    "attachments": [
        {
            "mimetype": "image/jpeg",
            "content": "R0lGODlhGQAZAPMHAAAAAFpaWv+gAN+MNdDWDfj/AH1t+P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAgALAAAAAAZABkAAASKEMlJq7046wvA3oDgfVwoklUnrMGJIia7jmS8zgFqFzdA5B+b4LAa+GgYIYA4MBKQpZagsGwOCE9JAGjxFb6FQGEgzopz267322Frw2dLq9P+BjxScfhyJ4C3Jy0texkdUgIGRjcsGgFYAAYGAE0maRmCj5OUlo1bWz8BZFwvgAKcLxOnqKusrRsRADs=",
            "filename": "chili-pepper.jpg"
        }
    ],
    "inlines": [
        {
            "mimetype": "image/jpeg",
            "filename": "chili-pepper-inline1.jpg"
        }
    ],
    "category": "wgnc:exclusive",
    "body_html": "<HTML><body><img src=\"cid:chili-pepper-inline1.jpg\"></body></HTML>",
    "text": "test_text",
    "subject": "Autotest subject"
}

with this schema:

{
    "description": "Email message",
    "type": "object",
    "properties": {
        "subject": {
            "type": "string",
            "minLength": 1,
            "pattern": "^[^\\r\\n\\t]+$"
        },
        "text": {
            "type": "string",
            "minLength": 1
        },
        "html": {
            "type": "string",
            "minLength": 1
        },
        "from": {
            "type": "string",
            "minLength": 1
        },
        "attachments": {
            "type": "array",
            "items": {
                "type": "object",
                "required": [
                    "filename",
                    "mimetype",
                    "content"
                ],
                "properties": {
                    "filename": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                    },
                    "mimetype": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                    },
                    "content": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 25000000,
                        "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
                    }
                }
            }
        },
        "inlines": {
            "type": "array",
            "items": {
                "type": "object",
                "required": [
                    "filename",
                    "mimetype",
                    "content"
                ],
                "properties": {
                    "filename": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                    },
                    "mimetype": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                    },
                    "content": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 25000000
                    }
                }
            }
        }
    },
    "anyOf": [
        {
            "required": [
                "subject",
                "html"
            ]
        },
        {
            "required": [
                "subject",
                "text"
            ]
        }
    ]
}

result is:

./_build/default/bin/jesse --json /Users/a_dziaineka/Repos/jesse/test_json/email_message.json -- /Users/a_dziaineka/Repos/jesse/test_json/test.json

{"filename":"/Users/a_dziaineka/Repos/jesse/test_json/test.json","result":"ok"}

But online validator found error (link to the case):

Message:
Required properties are missing from object: content.
Schema path:
#/properties/inlines/items/required

Is it a bug?

oneOf / anyOf with [{allowed_errors, infinity}] Doesn't work as expected

When allowed_errors option is set, oneOf and anyOf doesn't work.
You get an error back from the case that didn't match in the oneOf, which is not really an error, but the expected behaviour.

Here is the ct case I'm using.

jesse_one_of_issue(_Config) ->
    Schema = #{
        <<"$schema">> => <<"http://json-schema.org/draft-04/schema#">>,
        <<"type">> => <<"string">>,
        <<"oneOf">> => [
            #{<<"enum">> => [<<"my_enum">>]},
            #{<<"pattern">> => <<"^x-[a-z0-9\\-\\.]+$">>}
        ]
    },
    jesse:add_schema(test, Schema),
    % works
    GoodOpts = [],
    {ok, _} = jesse:validate(test, <<"my_enum">>, GoodOpts),
    {ok, _} = jesse:validate(test, <<"x-foo">>, GoodOpts),
    {error, _} = jesse:validate(test, <<"foo">>, GoodOpts),
    {error, _} = jesse:validate(test, <<"1-x">>, GoodOpts),
    % doesn't work
    BadOpts = [{allowed_errors, infinity}],
    {ok, _} = jesse:validate(test, <<"my_enum">>, BadOpts),
    {ok, _} = jesse:validate(test, <<"x-foo">>, BadOpts),
    {error, _} = jesse:validate(test, <<"foo">>, BadOpts),
    {error, _} = jesse:validate(test, <<"1-x">>, BadOpts).

how to reference keys

Hi,

I have a local id in file "test/test1.json" and how can I reference this file in another file somethgn like below?

"$ref" : "test/test1.json"

Module from rfc3339 dependency conflicts with module in jesse user application

Hi,

The dependency rfc3339 was introduced to implement date-time format validation in Draft 4 schemas. Unfortunately [for me] another RFC 3339 library with the same module name is used extensively through my application:

jesse:validate_with_schema(#{<<"type">> => <<"string">>, <<"format">> => <<"date-time">>}, <<"1970-01-01T00:00:00Z">>, [{default_schema_ver, <<"http://json-schema.org/draft-04/schema#">>}]).
** exception error: undefined function rfc3339:parse/1
     in function  jesse_validator_draft4:valid_datetime/1 (/home/me/proj/myapp/_build/default/lib/jesse/src/jesse_validator_draft4.erl, line 1349)
     in call from jesse_validator_draft4:check_format/3 (/home/me/proj/myapp/_build/default/lib/jesse/src/jesse_validator_draft4.erl, line 949)
     in call from jesse_validator_draft4:check_value/3 (/home/me/proj/myapp/_build/default/lib/jesse/src/jesse_validator_draft4.erl, line 217)
     in call from jesse_schema_validator:validate/3 (/home/me/proj/myapp/_build/default/lib/jesse/src/jesse_schema_validator.erl, line 45)
     in call from jesse:validate_with_schema/3 (/home/me/proj/myapp/_build/default/lib/jesse/src/jesse.erl, line 180)

If the issue isn't a «wontfix» one, there may be a few ways to fix it:

  • move date-time format validation to Draft 3 module, where due to more strict date-time format it can be reasonable implemented without any dependencies right in the jesse.
  • remove date-time format validation, allow user to store custom format validators in jesse database, suggest user to implement custom date-time format validator any way he finds suitable.
  • make the dependency optional somehow.
  • remove date-time format validation.

"required" has no effect

I am dynamically generating some JSON validation, but certain properties are not being validated against. Here's an example:

    Candidates = Election#election.candidates,
    Validation = {[{<<"type">>, <<"object">>},
                   {<<"properties">>,
                    {[{Candidate, {[{<<"type">>, <<"integer">>}]}} || Candidate <- Candidates]}},
                   {<<"required">>, Candidates},
                   {<<"additionalProperties">>, false}
                  ]},
    io:fwrite("Schema: ~s~n", [jiffy:encode(Validation)]),
    io:fwrite("~p~n", [Validation]),
    jesse:validate_with_schema(Validation, jiffy:decode(Body)).

And here's the output, along with a report of what was passed in if it passes validation:

Schema: {"type":"object","properties":{"x":{"type":"integer"},"y":{"type":"integer"},"z":{"type":"integer"}},"required":["x","y","z"],"additionalProperties":false}
{[{<<"type">>,<<"object">>},
  {<<"properties">>,
   {[{<<"x">>,{[{<<"type">>,<<"integer">>}]}},
     {<<"y">>,{[{<<"type">>,<<"integer">>}]}},
     {<<"z">>,{[{<<"type">>,<<"integer">>}]}}]}},
  {<<"required">>,[<<"x">>,<<"y">>,<<"z">>]},
  {<<"additionalProperties">>,false}]}
Passed validation: {[{<<"x">>,1}]}
Passed validation: {"x":1}

As you can see, when an object containing only one of the three required properties is passed in, it passes validation.

On the other hand, if I pass in {"i":1}, the validation fails according to the additionalProperties constraint.

Can you let me know what i'm doing wrong?

Improving the error messages from jesse when using oneOf/anyOf

When the JSON schema uses oneOf, anyOf or similar and the validation fails, the error message returned is not very helpful for the user. For example, in the case of oneOf the error is only not_one_schema_valid.

From what I've seen in the code, it should be possible to check all of the schemas in the specification provided in anyOf/oneOf, and add the errors from the schema with the least number of errors.

I am interested in implementing this change if you are willing to merge the PR 😄.

Return list of missing required fields

When validating an object against a schema with multiple fields in the required array (draft4), it would be great to get back either:

  1. {missing_required_property, [<<"foo">>, <<"bar">>]}
  2. Multiple 'data_invalid' tuples with each tuple having {missing_required_property, Key}

It looks straightforward enough in the code, something like (untested):

check_required(Value, [_|_]=Required, State) ->
    {_, Missing} = lists:partition(fun(Property) -> get_value(PropertyName, Value) =/= ?not_found end, Required),
    case Missing of
        [] -> State;
        MissingKeys -> %% do appropriate error return
    end;

Thoughts? Happy to submit the PR if this is a worthwhile change.

fix dialyzer issues

https://travis-ci.org/for-GET/jesse/jobs/95224229

jesse_error.erl:87: Function handle_data_invalid/3 has no local return
jesse_error.erl:100: Function handle_schema_invalid/2 has no local return
jesse_error.erl:109: Function handle_error/2 has no local return
jesse_error.erl:113: Fun application will fail since ErrorHandler :: fun(({'state',_,_,'undefined' | [binary()],'infinity' | 'undefined' | non_neg_integer(),'undefined' | [any()],'undefined' | fun(({'state',_,_,'undefined' | [binary()],'infinity' | 'undefined' | non_neg_integer(),'undefined' | [any()],'undefined' | fun(({'state',_,_,'undefined' | [binary()],'infinity' | 'undefined' | non_neg_integer(),'undefined' | [any()],'undefined' | fun((_) -> [any()]),atom()}) -> [any()]),atom()}) -> [any()]),atom()}) -> [any()]) is not a function of arity 3
jesse_state.erl:84: Invalid type specification for function jesse_state:get_default_schema_ver/1. The success typing is (#state{current_path::'undefined' | [binary()],allowed_errors::'infinity' | 'undefined' | non_neg_integer(),error_list::'undefined' | [any()],error_handler::'undefined' | fun((#state{current_path::'undefined' | [any()],allowed_errors::'infinity' | 'undefined' | non_neg_integer(),error_list::'undefined' | [any()],error_handler::'undefined' | fun((_) -> any()),default_schema_ver::atom()}) -> [any()]),default_schema_ver::atom()} | jesse_state:state()) -> atom()
jesse_validator_draft3.erl:304: Function wrong_type/2 has no local return
jesse_validator_draft3.erl:405: The created fun has no local return
jesse_validator_draft3.erl:405: The call lists:foldl(fun((_,_) -> none()),State::jesse_state:state(),Extras::[{atom() | binary() | [any()],_},...]) will never return since the success typing arguments are (fun((_,_) -> any()),any(),[any()])
jesse_validator_draft3.erl:492: The created fun has no local return
jesse_validator_draft3.erl:494: The call jesse_validator_draft3:check_value(Index::number(),Item::any(),Items::any(),CurrentState::any()) will never return since it differs in the 1st argument from the success typing arguments: (binary(),any(),any(),jesse_state:state())
jesse_validator_draft3.erl:541: The created fun has no local return
jesse_validator_draft3.erl:546: The call jesse_validator_draft3:check_value(Index::number(),Item::any(),Schema::any(),NewState::jesse_state:state()) will never return since it differs in the 1st argument from the success typing arguments: (binary(),any(),any(),jesse_state:state())
jesse_validator_draft3.erl:848: The call jesse_validator_draft3:check_value('extends',Value::any(),Extends::any(),jesse_state:state()) will never return since it differs in the 1st argument from the success typing arguments: (binary(),any(),any(),jesse_state:state())
jesse_validator_draft3.erl:939: Function handle_data_invalid/3 has no local return
jesse_validator_draft3.erl:943: Function handle_schema_invalid/2 has no local return
jesse_validator_draft3.erl:963: Function remove_last_from_path/1 will never be called

Add maps support

It will be great, if we can validate map() JSON representation (at least map data, not map schema).

jiffy:decode(<<...>>, return_maps).

I've already made pull-request to kvc with maps support etrepum/kvc#9 (not merged yet). But changes may be ported right now. (Why we use our own copy of kvc instead of rebar dep?).

Also, I'm ready to implement this myself, if someone is interested to review it.

Tagged release

Hey,

We are updating jesse internally and would like to use upstream version numbers. Any chance we could get a tagged release of the current version?

breaks with [email protected]

1683 was green: https://travis-ci.org/github/for-GET/jesse/builds/749489608
1684 was red: https://travis-ci.org/github/for-GET/jesse/builds/750746033

@paulo-ferraz-oliveira would you be so kind to have a look? I see you're active there.

I'm locking it to 0.2.0 for now. Should probably be locked anyway.

Details
# src/jesse.erl [FAIL]
192Error: 'undef' while applying rule 'no_trailing_whitespace'.
193Error: 'undef' while applying rule 'no_tabs'.
194Error: 'undef' while applying rule 'line_length'.
195# src/jesse_cli.erl [FAIL]
196Error: 'undef' while applying rule 'no_trailing_whitespace'.
197Error: 'undef' while applying rule 'no_tabs'.
198Error: 'undef' while applying rule 'line_length'.
199# src/jesse_database.erl [FAIL]
200Error: 'undef' while applying rule 'no_trailing_whitespace'.
201Error: 'undef' while applying rule 'no_tabs'.
202Error: 'undef' while applying rule 'line_length'.
203# src/jesse_error.erl [FAIL]
204Error: 'undef' while applying rule 'no_trailing_whitespace'.
205Error: 'undef' while applying rule 'no_tabs'.
206Error: 'undef' while applying rule 'line_length'.
207# src/jesse_json_path.erl [FAIL]
208  - macro_names
209    - The macro named "Exp" on line 19 does not respect the format defined by the regular expression '"^([A-Z][A-Z_0-9]+)$"'.
210Error: 'undef' while applying rule 'no_trailing_whitespace'.
211Error: 'undef' while applying rule 'no_tabs'.
212Error: 'undef' while applying rule 'line_length'.
213# src/jesse_lib.erl [FAIL]
214Error: 'undef' while applying rule 'no_trailing_whitespace'.
215Error: 'undef' while applying rule 'no_tabs'.
216Error: 'undef' while applying rule 'line_length'.
217# src/jesse_schema_validator.erl [FAIL]
218Error: 'undef' while applying rule 'no_trailing_whitespace'.
219Error: 'undef' while applying rule 'no_tabs'.
220Error: 'undef' while applying rule 'line_length'.
221# src/jesse_state.erl [FAIL]
222Error: 'undef' while applying rule 'no_trailing_whitespace'.
223Error: 'undef' while applying rule 'no_tabs'.
224Error: 'undef' while applying rule 'line_length'.
225# src/jesse_tests_util.erl [FAIL]
226Error: 'undef' while applying rule 'no_trailing_whitespace'.
227Error: 'undef' while applying rule 'no_tabs'.
228Error: 'undef' while applying rule 'line_length'.
229# src/jesse_validator_draft3.erl [FAIL]
230Error: 'undef' while applying rule 'no_trailing_whitespace'.
231Error: 'undef' while applying rule 'no_tabs'.
232Error: 'undef' while applying rule 'line_length'.
233# src/jesse_validator_draft4.erl [FAIL]
234Error: 'undef' while applying rule 'no_trailing_whitespace'.
235Error: 'undef' while applying rule 'no_tabs'.
236Error: 'undef' while applying rule 'line_length'.
237# test/jesse_json_path_tests.erl [FAIL]
238Error: 'undef' while applying rule 'no_trailing_whitespace'.
239Error: 'undef' while applying rule 'no_tabs'.
240Error: 'undef' while applying rule 'line_length'.
241# test/jesse_schema_validator_tests.erl [FAIL]
242Error: 'undef' while applying rule 'no_trailing_whitespace'.
243Error: 'undef' while applying rule 'no_tabs'.
244Error: 'undef' while applying rule 'line_length'.
245# test/jesse_tests_draft3_SUITE.erl [FAIL]
246Error: 'undef' while applying rule 'no_trailing_whitespace'.
247Error: 'undef' while applying rule 'no_tabs'.
248Error: 'undef' while applying rule 'line_length'.
249# test/jesse_tests_draft4_SUITE.erl [FAIL]
250Error: 'undef' while applying rule 'no_trailing_whitespace'.
251Error: 'undef' while applying rule 'no_tabs'.
252Error: 'undef' while applying rule 'line_length'.
253===> Linting failed
254

Performance issues

I was looking at jesse's performance, with one or two dozen of schemas that I added with more or less arbitrary keys via jesse:add_schema("some key", SchemaData, [{parser_fun, fun jsx:decode/1}]).
When doing validation I found that (at least on my MacOS box with SSD), about 30% of the run-time is used in treating my arbitrary key as a relative file name. I found it's was a bit better on some other machines/OSes, but jesse_state:canonical_path consistently used a large part of the run time in my tests. Just making my "arbitrary keys" start with "http://" (so canonical_path uses string functions instead of filename functions) gave me a 30% speedup (run time for a single pass of my little test suite dropped from roughly 160 ms to 110 ms).
IMHO implicitly treating such arbitrary keys (that don't start with "file://") as files comes as a surprise to the user of jesse. Why not have that last clause of canonical_path just return the arbitrary key that was given to it, instead of forcibly treating it as a file name and "upgrading" it to a "file://" URI? Having to explicitly create an invalid URI like "http://some.name" and use that as a key, just to avoid that runtime penalty, feels really strange.

And then you just released 1.5.0, so of course I was curious about how that would affect performance. After a quick glance at the source code, I didn't have much hope that I would be freed from the need to prefix my keys with "http://" - and indeed, I wasn't.

Much worse, compared to the git version I used up to now (bd1c7e5), runtimes roughly doubled. I.e. I did all this profiling and testing to get the runtime of my testsuite down from 160 ms to 110 ms and after updating to the latest jesse release I'm now at 210 ms (and if I remove that hack with the "http://" prefix for testing, it's way over 300 ms). After doing some profiling on 1.5.0, I can't really point to a specific place in the code (like I could with jesse_state:canonical_path) and say that's where you are using up all that additional time, so for now I can only report those results to you and hope that maybe you can figure out how to speed things up again ...

Since you are possibly wondering why anyone would care about jesse's performance: Think of e.g. a cowboy server which receives JSON requests from clients, validates these requests and replies either with ok (and starts a job on a backend server) or with an error message about an invalid JSON. In that scenario jesse is really consuming a large chunk of the runtime on that frontend. And since I'm hoping for lots and lots of clients, jesse validation really becomes a bottleneck during traffic spikes.

More $ref resolution questions

Let's say I have a "common" schema with common data types for a few different schemas.

{
  "$id": "http://example.com/schema/common.json",
  "definitions": {
    "account_id": {
      "$id": "#account_id",
      "description": "A valid customer account id",
      "type": "integer"
    },
    "media-type": {
      "$id": "#media_type",
      "description": "A MIME media type",
      "type": "string"
    }
  }
}

And then I have another schema file

{
  "$id": "http://example.com/schema/customer-data.json",
  "properties": {
    "account_id": { "$ref": "common.json#account_id" },
    "media_type": { "$ref": "common.json#media-type" }
  }
}

When I try this, I get

{error,[{schema_invalid,#{<<"$ref">> => <<"common.json#account_id">>},
 {schema_not_found,"file:///Users/mallen/sandbox/_build/test1/lib/test1/priv/schema/common.json#account_id"}}]}

How can I get this to resolve?

add jesse:error_to_json

Port of klarna/jesse#38 by @Licenser


Hi, I was thinking it'd be really nice to have a pre-build function that formats the erlang error into a json error to return to the sender.

It probably can be done easily in the application using jesse but it seems such a common thing that I feel like it could be included directly?

-spec error_to_json([jesse:error()]) -> binary().
%% ...
something like that?

Contradictory behavior when used $ref

Working example:

ok = jesse:add_schema("./schema3", #{
    <<"id">> => <<"schema3">>,
    <<"type">> => <<"object">>,
    <<"properties">> => #{
        <<"key3">> => #{
            <<"type">> => <<"string">>
        }
    }
}).
ok = jesse:add_schema("./schema2", #{
    <<"id">> => <<"schema2">>,
    <<"type">> => <<"object">>,
    <<"properties">> => #{
        <<"key2">> => #{
            <<"allOf">> => [
                #{<<"$ref">> => <<"schema3">>}
            ]
        }
    }
}).
ok = jesse:add_schema("./schema1", #{
    <<"id">> => <<"schema1">>,
    <<"properties">> => #{
        <<"key1">> => #{
            <<"allOf">> => [
                #{<<"$ref">> => <<"schema2">>}
            ]
        }
    }
}).
{ok, _} =  jesse:validate("./schema1", #{<<"key1">> => #{<<"key2">> => #{<<"key3">> => <<"123">>}}}, [
    {default_schema_ver, <<"http://json-schema.org/draft-04/schema#">>}
]).

Problems:

  1. Name of schema does not match to name that should be in $ref
  2. If to delete id from schemas - example does not work
  3. The items 1 and 2 is not valid and example works in simple manner (withot id and with clear naming) when used only two levels of nested.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.