for-GET / jesse

jesse (JSon Schema Erlang) is an implementation of a JSON Schema validator for Erlang.
https://github.com/for-get/jesse
Apache License 2.0
124 stars 64 forks source link

inconsistent behavior with atoms as labels in schema and JSON #126

Closed RoadRunnr closed 1 year ago

RoadRunnr commented 1 year ago

jsx can parse labels to atoms and also serialize atoms in labels as strings. When using this for the schemas and/or the JSON, the validation results are inconsistent and in many cases plain wrong.

When using atom labels in the schema, validations seems be to totally broken. In this sample, schema validation should return invalid types for a, b, and c, but it doesn't. There is no difference in whether the labels in the JSON are atoms or binary.

2> Schema = jsx:decode(<<"{\"properties\": {\"a\": {\"type\": \"integer\"}, \"b\": {\"type\": \"string\"}, \"c\": {\"type\": \"boolean\"}}, \"additionalProperties\": false}">>, [{labels, atom}]). 
#{additionalProperties => false,
  properties =>
      #{a => #{type => <<"integer">>},
        b => #{type => <<"string">>},
        c => #{type => <<"boolean">>}}}
3> jesse:validate_with_schema(Schema, #{a => true, b => 2, c => 3}, [{allowed_errors, infinity}]).                                                                                                  
{ok,#{a => true,b => 2,c => 3}}
4> jesse:validate_with_schema(Schema, #{a => true, b => 2, <<"c">> => 3}, [{allowed_errors, infinity}]).
{ok,#{a => true,b => 2,<<"c">> => 3}}

When using binaries as labels in the schema and atom in the JSON, validation results are "strange":

1> Schema = jsx:decode(<<"{\"properties\": {\"a\": {\"type\": \"integer\"}, \"b\": {\"type\": \"string\"}, \"c\": {\"type\": \"boolean\"}}, \"additionalProperties\": false}">>). 
#{<<"additionalProperties">> => false,
  <<"properties">> =>
      #{<<"a">> => #{<<"type">> => <<"integer">>},
        <<"b">> => #{<<"type">> => <<"string">>},
        <<"c">> => #{<<"type">> => <<"boolean">>}}}
2> jesse:validate_with_schema(Schema, #{a => true, b => 2, c => 3}, [{allowed_errors, infinity}]).                                                                                
{error,[{data_invalid,#{<<"additionalProperties">> => false,
                        <<"properties">> =>
                            #{<<"a">> => #{<<"type">> => <<"integer">>},
                              <<"b">> => #{<<"type">> => <<"string">>},
                              <<"c">> => #{<<"type">> => <<"boolean">>}}},
                      no_extra_properties_allowed,
                      #{a => true,b => 2,c => 3},
                      [a]},
        {data_invalid,#{<<"additionalProperties">> => false,
                        <<"properties">> =>
                            #{<<"a">> => #{<<"type">> => <<"integer">>},
                              <<"b">> => #{<<"type">> => <<"string">>},
                              <<"c">> => #{<<"type">> => <<"boolean">>}}},
                      no_extra_properties_allowed,
                      #{a => true,b => 2,c => 3},
                      [b]},
        {data_invalid,#{<<"additionalProperties">> => false,
                        <<"properties">> =>
                            #{<<"a">> => #{<<"type">> => <<"integer">>},
                              <<"b">> => #{<<"type">> => <<"string">>},
                              <<"c">> => #{<<"type">> => <<"boolean">>}}},
                      no_extra_properties_allowed,
                      #{a => true,b => 2,c => 3},
                      [c]},
        {data_invalid,#{<<"type">> => <<"integer">>},
                      wrong_type,true,
                      [<<"a">>]},
        {data_invalid,#{<<"type">> => <<"string">>},
                      wrong_type,2,
                      [<<"b">>]},
        {data_invalid,#{<<"type">> => <<"boolean">>},
                      wrong_type,3,
                      [<<"c">>]}]}

It does pick up the wrong data types for a, b and c, but it also reports all the fields with an no_extra_properties_allowed error.

RoadRunnr commented 1 year ago

something went wrong when creating this ticket and it ended up being created twice, closing the duplciate