Skip to content

feat(validate): add --path option to target sub-schema via JSON Pointer#696

Open
Vaibhav701161 wants to merge 6 commits intosourcemeta:mainfrom
Vaibhav701161:feat/validate-path-option
Open

feat(validate): add --path option to target sub-schema via JSON Pointer#696
Vaibhav701161 wants to merge 6 commits intosourcemeta:mainfrom
Vaibhav701161:feat/validate-path-option

Conversation

@Vaibhav701161
Copy link
Copy Markdown
Contributor

Description

This PR adds support for a --path option to the validate command. It allows validating a specific sub-schema inside a larger JSON document using a JSON Pointer.

Reference #218


Motivation

In practice, most schemas are not standalone. They are often embedded inside larger documents such as OpenAPI specs. Right now, validating those requires manually extracting the schema first, which is inconvenient.

This change makes that workflow much simpler. You can directly point to the part of the document you want to validate.

Example:

jsonschema validate openapi.json instance.json \
  --path /components/schemas/User

This also fits with the direction discussed in #80, where the goal is to make it easier to work with embedded schemas without needing full OpenAPI parsing.


What this does

  • Adds a new --path <pointer> option to validate
  • Uses existing utilities (to_pointer, try_get) to resolve the JSON Pointer
  • Extracts the target sub-schema before running validation, so the rest of the pipeline stays unchanged
  • Adds a check to prevent using --path together with --template
  • Updates the CLI help text

Error handling

  • If the pointer does not resolve, validation fails using existing schema error handling
  • If the resolved value is not a valid schema, existing validation checks handle it
  • Invalid pointer syntax behaves the same way as other pointer-based options such as --entrypoint

No new error types are introduced. Existing ones are reused to stay consistent with current CLI behavior.


Tests

Added a small set of tests following existing patterns:

  • pass_path_openapi checks validating a schema inside an OpenAPI document
  • fail_path_not_found checks when the pointer does not resolve
  • fail_path_not_schema checks when the resolved value is not a schema
  • fail_path_with_template checks the CLI option conflict

Tests focus on exit codes and stable output to avoid fragile assertions.


Notes

This change is intentionally scoped to validate as a first step. It keeps the implementation simple and consistent with existing patterns.

It also provides a practical way to work with embedded schemas today, while leaving room for broader OpenAPI support in the future.

Copilot AI review requested due to automatic review settings March 28, 2026 08:16
@Vaibhav701161
Copy link
Copy Markdown
Contributor Author

Hi @jviotti, could you take a look when you have time? Would love your thoughts, especially if there are any edge cases I missed.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a --path option to the validate CLI command so users can target and validate a sub-schema inside a larger JSON/YAML document via JSON Pointer (e.g., OpenAPI documents).

Changes:

  • Adds --path <pointer> to the validate command and documents it in CLI help.
  • Extracts the pointed sub-schema before running the existing validation pipeline and blocks --path + --template together.
  • Adds new validate CLI tests for success and failure cases involving --path.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/command_validate.cc Implements --path extraction logic and adds --path/--template conflict handling.
src/main.cc Registers the new validate option and updates CLI help text.
test/CMakeLists.txt Adds the new validate --path shell tests to the test suite.
test/validate/pass_path_openapi.sh Validates extracting a schema embedded in an OpenAPI-like document.
test/validate/fail_path_not_found.sh Asserts failure when the pointer doesn’t resolve.
test/validate/fail_path_not_schema.sh Asserts failure when the pointed value isn’t a schema.
test/validate/fail_path_with_template.sh Asserts CLI argument conflict handling for --path with --template.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@augmentcode
Copy link
Copy Markdown

augmentcode bot commented Mar 28, 2026

🤖 Augment PR Summary

Summary: This PR adds a --path option to the validate command so users can validate a sub-schema embedded inside a larger JSON/YAML document via JSON Pointer.

Changes:

  • Added CLI parsing and help text for jsonschema validate ... --path <pointer>.
  • Implemented pointer resolution in command_validate.cc using to_pointer + try_get, then validates/bundles the extracted sub-schema.
  • Added an explicit option conflict: --path cannot be combined with --template.
  • Kept existing validation/bundling pipeline unchanged by performing extraction before schema checks and bundling.
  • Added Unix shell tests covering: success on OpenAPI-like documents, pointer not found, target not a schema, and conflict with --template.

Technical Notes: The implementation copies the pointed-to sub-schema before reassigning to avoid aliasing/use-after-free when the pointer references the same underlying JSON storage.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 7 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="test/CMakeLists.txt">

<violation number="1" location="test/CMakeLists.txt:232">
P2: New `--path` failure tests are registered without JSON-error assertions for two failure modes, leaving structured error output untested.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="test/validate/fail_path_ref_outside_subtree.sh">

<violation number="1" location="test/validate/fail_path_ref_outside_subtree.sh:32">
P2: New failure test lacks a companion `--json` assertion, so structured error output for this scenario is not covered.</violation>

<violation number="2" location="test/validate/fail_path_ref_outside_subtree.sh:36">
P2: Failure test is too broad: it suppresses output and only checks for any non-zero exit code, so unrelated errors can falsely pass.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

// Invalid pointer syntax is handled by to_pointer(), consistent with
// --entrypoint behavior.
const auto path_string{std::string{options.at("path").front()}};
const auto pointer{sourcemeta::core::to_pointer(path_string)};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider handling invalid JSON Pointer syntax from to_pointer(...) explicitly (e.g., wrap into a handled FileError similar to how resolve_entrypoint maps pointer errors); otherwise this will fall through to the generic handler and surface as an unexpected error instead of a schema input error.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.


const auto schema{schema_from_stdin
? read_from_stdin().document
sourcemeta::core::JSON schema{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note you can still do auto here

: sourcemeta::core::read_yaml_or_json(schema_path)};

if (options.contains("path") && !options.at("path").empty()) {
// Invalid pointer syntax is handled by to_pointer(), consistent with
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment can go away. If any, cover it with a test

if (options.contains("path") && !options.at("path").empty()) {
// Invalid pointer syntax is handled by to_pointer(), consistent with
// --entrypoint behavior.
const auto path_string{std::string{options.at("path").front()}};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we pass this directly to to_pointer?

if (!result) {
throw NotSchemaError{schema_resolution_base};
}
// Note: extracting a sub-schema may break $ref references outside the
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment can go away too. We can assert on this behaviour in the tests and instead explain in the docs.

Which reminds be that you didn't update the docs!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, we probably want something like this for the compile command too

src/main.cc Outdated
non-sense results.

Use --path to extract a sub-schema from the input document using
a JSON Pointer before validation. This is useful for validating
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would omit the second sentence about where this is useful. We can keep this help message more concise and explain more in the actual markdown docs?

src/main.cc Outdated
app.option("template", {"m"});
app.option("loop", {"l"});
app.option("entrypoint", {"p"});
app.option("path", {});
Copy link
Copy Markdown
Member

@jviotti jviotti Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a short version to it too?

# Schema input error
test "$EXIT_CODE" = "4"

cat << EOF > "$TMP/expected.txt"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For every error, please also run it with --json like the other test files

test "$EXIT_CODE" = "4"

cat << EOF > "$TMP/expected.txt"
error: The schema file you provided does not represent a valid JSON Schema
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm I think the error message makes no sense. Can we create a more meaningful exception class in src/error.h and throw that instead? You can do the try_get, and if not there, throw that new error?

"$1" validate "$TMP/document.json" "$TMP/instance.json" \
--path "/components/schemas/NonExistent" 2> "$TMP/stderr.txt" \
&& EXIT_CODE="$?" || EXIT_CODE="$?"
# Schema input error
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this is not a schema input error for a general input error. Can you check the exit code constants? Is this indeed the most appropriate one?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, seems like it should be 5?

# Schema input error
test "$EXIT_CODE" = "4"

cat << EOF > "$TMP/expected.txt"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. If testing errors, always also run it with --json. See other failure tests


cat << EOF > "$TMP/expected.txt"
error: The schema file you provided does not represent a valid JSON Schema
at file path $(realpath "$TMP")/document.json
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the error here is not that bad, but we should be printing the pointer too, with at pointer / at location or whatever we do with similar ones. So maybe worth subclassing this exception class in src/error.h?

error: Could not resolve schema reference
at identifier file://$(realpath "$TMP")/document.json#/components/schemas/Address
at file path $(realpath "$TMP")/document.json
at location "/\$ref"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need to subclass this exception class to add the actual pointer from --path. Maybe what we do is always append that as from path <pointer>?

EOF

diff "$TMP/stdout.txt" "$TMP/expected.txt"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blank line

{ "name": "John", "age": 30 }
EOF

"$1" validate "$TMP/openapi.json" "$TMP/instance.json" \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you run this with --verbose and then assert on the output? That will help us indeed assert on the result. And maybe do one with --json too

@Vaibhav701161 Vaibhav701161 force-pushed the feat/validate-path-option branch from e6bc54c to 9942324 Compare April 5, 2026 18:54
Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
…ests, and behavior documentation)

Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
@Vaibhav701161 Vaibhav701161 force-pushed the feat/validate-path-option branch from 9942324 to de9cd5e Compare April 8, 2026 10:48
Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
- Change PathResolutionError exit code from 6 to 5 (EXIT_INVALID_CLI_ARGUMENTS)
- Add pointer field to NotSchemaError, print when --path is used
- Create PathSchemaReferenceError for  errors with --path context
- Guard empty pointer strings in print_exception
- Remove unnecessary use-after-free comment
- Move is_schema check inside --path block for correct pointer propagation
- Update all test expectations

Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
@Vaibhav701161 Vaibhav701161 requested a review from jviotti April 8, 2026 12:27
@Vaibhav701161
Copy link
Copy Markdown
Contributor Author

@jviotti , any comments ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants