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

Support draft-04 (and other?) JSON schemas #493

Closed
mtmorgan opened this issue Feb 25, 2024 · 10 comments · Fixed by microsoft/vcpkg#38532
Closed

Support draft-04 (and other?) JSON schemas #493

mtmorgan opened this issue Feb 25, 2024 · 10 comments · Fixed by microsoft/vcpkg#38532

Comments

@mtmorgan
Copy link
Contributor

mtmorgan commented Feb 25, 2024

Describe the proposed feature

Currently, validation requires schemas following the 'draft-07' schema, but many schemas 'in the wild' are draft-04, an example relevant to jsoncon is JSON patch https://json.schemastore.org/json-patch.json.

What other libraries (C++ or other) have this feature?

I think many other libraries support, to one extent or another, draft-04

Include a code fragment with sample data that illustrates the use of this feature

#include "jsoncons_ext/jsonschema/jsonschema.hpp"

using namespace jsoncons;

int main(int argc, char *argv[])
{
    json schema = json::parse(R"(
{
    "$schema": "http://json-schema.org/draft-04/schema#"
}
    )");
    auto sch = jsonschema::make_schema(schema);
}

leads to

$ ./a.out
libc++abi: terminating due to uncaught exception of type jsoncons::jsonschema::schema_error: Unsupported schema version http://json-schema.org/draft-04/schema#
zsh: abort      ./a.out

Apparently the changes from 04 to 06 are minor and 07 is backward-compatible with 06.

I could develop a pull request, but likely there would be a lot of 'mentoring' ;) involved to make it worth-while.

@danielaparker
Copy link
Owner

We're currently in the process of restructuring the jsonschema code to accommodate multiple versions. The current focus is on Draft 2019-09, to be followed by 2012-12. I hadn't really thought about it, but I suppose adding 04 and 06 wouldn't be a big deal.

@danielaparker
Copy link
Owner

make_json_schema on master now supports drafts 04 and 06, in addition to 07, 2019-09, and 2020-12. It will detect the appropriate schema using $schema, if present, or if not, from the evaluation option default_version.

@mtmorgan
Copy link
Contributor Author

mtmorgan commented Apr 2, 2024

Amazing!

I notice when validating the JSONPatch [{"op": "adds", "paths": "/biscuits/1", "value": { "name": "Ginger Nut" }}] against https://json.schemastore.org/json-patch.json, the details provide errors containing single- ('paths'), double- ("paths"), and unquoted (adds) values / properties; it would be great if this were consistent (with single quotes being my preferred flavor...).

"Required property \"path\" not found"
"adds is not a valid enum value"
"Additional property 'paths' but the schema does not allow additional properties."

Happy to provide a PR...

@danielaparker
Copy link
Owner

@mtmorgan Feel free to submit a PR with cleaned up error messages, I agree with single quote consistency. The validation messages are mostly constructed in the file jsonschema/common/keyword_validators.hpp. Please take the most recent copy of master, there's been one name change with the new classes, schema -> schema_version.

@mtmorgan
Copy link
Contributor Author

mtmorgan commented Apr 6, 2024

I notice that

    jsoncons::ojson schema_;
    auto compiled = jsoncons::jsonschema::make_json_schema(schema_);

fails to compile with error

no matching function for call to object of type 'schema_builder_factory<basic_json<char, order_preserving_policy, allocator>>'

No problem for jsoncons::json.

@danielaparker
Copy link
Owner

@mtmorgan Should be fixed on master

@mtmorgan
Copy link
Contributor Author

mtmorgan commented Apr 7, 2024

Trying to validate a JSON patch 'op' against the patch schema seems to result in an incorrect 'evaluationPath' with /items/0/oneOf instead of what I think should be /items/oneOf (the 0/ is correctly included in 'details', if I understand correctly).

#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonschema/jsonschema.hpp>

int main(int argc, char *argv[])
{
    std::string schema_string = R"(
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "definitions": {
    "path": {
      "description": "A JSON Pointer path.",
      "type": "string"
    }
  },
  "id": "https://json.schemastore.org/json-patch.json",
  "items": {
    "oneOf": [
      {
        "additionalProperties": false,
        "required": ["value", "op", "path"],
        "properties": {
          "path": {
            "$ref": "#/definitions/path"
          },
          "op": {
            "description": "The operation to perform.",
            "type": "string",
            "enum": ["add", "replace", "test"]
          },
          "value": {
            "description": "The value to add, replace or test."
          }
        }
      },
      {
        "additionalProperties": false,
        "required": ["op", "path"],
        "properties": {
          "path": {
            "$ref": "#/definitions/path"
          },
          "op": {
            "description": "The operation to perform.",
            "type": "string",
            "enum": ["remove"]
          }
        }
      },
      {
        "additionalProperties": false,
        "required": ["from", "op", "path"],
        "properties": {
          "path": {
            "$ref": "#/definitions/path"
          },
          "op": {
            "description": "The operation to perform.",
            "type": "string",
            "enum": ["move", "copy"]
          },
          "from": {
            "$ref": "#/definitions/path",
            "description": "A JSON Pointer path pointing to the location to move/copy from."
          }
        }
      }
    ]
  },
  "title": "JSON schema for JSONPatch files",
  "type": "array"
})";

    std::string data_string = R"([
{
    "op": "invalid_op",
    "path": "/biscuits/1",
    "value":{"name":"Ginger Nut" }
}])";

    auto schema_ = jsoncons::ojson::parse(schema_string);
    auto data_ = jsoncons::ojson::parse(data_string);
    auto compiled = jsoncons::jsonschema::make_json_schema(schema_);
    jsoncons::json_decoder<jsoncons::ojson> decoder;
    compiled.validate(data_, decoder);
    auto output = decoder.get_result();

    std::cout << pretty_print(output) << std::endl;

    return 0;
}

producing in part

...
        "evaluationPath": "/items/0/oneOf", 
...
        "details": [
            {
                "valid": false, 
                "evaluationPath": "/items/0/oneOf/0/additionalProperties/properties/op/enum", 
...

@danielaparker
Copy link
Owner

Thanks! That observation was very helpful. Should be fixed on master.

@mtmorgan
Copy link
Contributor Author

mtmorgan commented Apr 8, 2024

I'm not sure the paths are correct yet? I see

{
                "error": "'invalid_op' is not a valid enum value.", 
                "evaluationPath": "/items/oneOf/0/additionalProperties/properties/op/enum", 
                "instanceLocation": "/0/op", 
                "schemaLocation": "https://json.schemastore.org/json-patch.json#/items/oneOf/0/properties/op/enum", 
                "valid": false
            },

but the evaluationPath does not exist in the schema? Or maybe I'm misunderstanding...?

@danielaparker
Copy link
Owner

I'm not sure either :-) Suspect they aren't.

Anyway that one is a separate issue that should be fixed now on master.

data-queue pushed a commit to microsoft/vcpkg that referenced this issue May 3, 2024
<!-- If your PR fixes issues, please note that here by adding "Fixes
#NNNNNN." for each fixed issue on separate lines. -->

Fixes danielaparker/jsoncons#502
Fixes danielaparker/jsoncons#501
Fixes danielaparker/jsoncons#499
Fixes danielaparker/jsoncons#496
Fixes danielaparker/jsoncons#493
Fixes danielaparker/jsoncons#490

<!-- If you are still working on the PR, open it as a Draft:
https://github.blog/2019-02-14-introducing-draft-pull-requests/. -->

<!-- If this PR updates an existing port, please uncomment and fill out
this checklist:

- [x] Changes comply with the [maintainer
guide](https://github.com/microsoft/vcpkg-docs/blob/main/vcpkg/contributing/maintainer-guide.md).
- [x] SHA512s are updated for each updated download.
- [x] The "supports" clause reflects platforms that may be fixed by this
new version.
- [x] Any fixed [CI
baseline](https://github.com/microsoft/vcpkg/blob/master/scripts/ci.baseline.txt)
entries are removed from that file.
- [x] Any patches that are no longer applied are deleted from the port's
directory.
- [x] The version database is fixed by rerunning `./vcpkg x-add-version
--all` and committing the result.
- [x] Only one version is added to each modified port's versions file.
yurybura pushed a commit to yurybura/vcpkg that referenced this issue May 8, 2024
<!-- If your PR fixes issues, please note that here by adding "Fixes
#NNNNNN." for each fixed issue on separate lines. -->

Fixes danielaparker/jsoncons#502
Fixes danielaparker/jsoncons#501
Fixes danielaparker/jsoncons#499
Fixes danielaparker/jsoncons#496
Fixes danielaparker/jsoncons#493
Fixes danielaparker/jsoncons#490

<!-- If you are still working on the PR, open it as a Draft:
https://github.blog/2019-02-14-introducing-draft-pull-requests/. -->

<!-- If this PR updates an existing port, please uncomment and fill out
this checklist:

- [x] Changes comply with the [maintainer
guide](https://github.com/microsoft/vcpkg-docs/blob/main/vcpkg/contributing/maintainer-guide.md).
- [x] SHA512s are updated for each updated download.
- [x] The "supports" clause reflects platforms that may be fixed by this
new version.
- [x] Any fixed [CI
baseline](https://github.com/microsoft/vcpkg/blob/master/scripts/ci.baseline.txt)
entries are removed from that file.
- [x] Any patches that are no longer applied are deleted from the port's
directory.
- [x] The version database is fixed by rerunning `./vcpkg x-add-version
--all` and committing the result.
- [x] Only one version is added to each modified port's versions file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants