ITADN

JSON Schema 2020-12: `$ref` resolution with `$id`/`$anchor`

#9333Closedssevertson-svg 创建于 2026-03-18
S
ssevertson-svgcommented
### Issue workflow progress _Progress of the issue based on the [Contributor Workflow](https://github.com/the-guild-org/Stack/blob/master/CONTRIBUTING.md#a-typical-contributor-workflow)_ - [x] 1. The issue provides a reproduction (MRE attached with synthetic specs, see below) - [ ] 2. A failing test has been provided - [ ] 3. A local solution has been provided - [ ] 4. A pull request is pending review --- **Describe the bug** We hit this while trying to load the [Petstore 3.1 spec](https://petstore31.swagger.io/) through `loadOpenAPISubgraph`. It fails with `ENOENT` errors because `json-machete`'s `dereferenceObject` treats `$id`-based `$ref` URIs as filesystem paths. The Petstore 3.1 spec uses two JSON Schema 2020-12 reference patterns that break: `$id` as a `$ref` target: `Category` declares `$id: /api/v31/components/schemas/category`, and `PetDetails.category` references it with `$ref: /api/v31/components/schemas/category`. `dereferenceObject` splits on `#`, sees no fragment, and calls `readFile('/api/v31/components/schemas/category')`. `$anchor` fragment references: `PetDetails.id` declares `$anchor: pet_details_id` inside a schema with `$id: /api/v31/components/schemas/petdetails`. `Pet.petDetailsId` uses `$ref: /api/v31/components/schemas/petdetails#pet_details_id`. The left side gets the same file-path treatment, and `pet_details_id` is interpreted as a JSON Pointer when it's actually an anchor name. Worth noting: OpenAPI 3.1 specs that stick to JSON Pointer refs (`#/components/schemas/...`) work fine. The problem is specifically `$ref` resolution when `$id`/`$anchor` semantics are involved. **To Reproduce** [json-schema-2020-12-edge-cases.tgz](https://github.com/user-attachments/files/26098850/json-schema-2020-12-edge-cases.tgz) The attached MRE has four minimal OpenAPI 3.1 specs, each isolating one feature: ```sh npx tsx reproduce.ts ``` ``` JSON Schema 2020-12 Edge Cases — @omnigraph/openapi ════════════════════════════════════════════════════ @omnigraph/openapi: 0.109.36 Origin: Petstore 3.1 (https://petstore31.swagger.io/) ✓ Standard JSON Pointer $ref ("#/components/schemas/...") 7 types: Query, Item, Category, HTTPMethod, ObjMap, String, Boolean ✗ $id URI used as $ref target (JSON Schema 2020-12 §8.2.1) Unable to load /schemas/category from <cwd>/specs ✗ $anchor + $id#anchor $ref pattern (JSON Schema 2020-12 §8.2.2) Unable to load /schemas/details from <cwd>/specs ✓ $ref with sibling keywords (OpenAPI 3.1 / JSON Schema 2020-12) 10 types: Query, Item, Int, Mutation, JSON, Item_Input, HTTPMethod, ObjMap, String, Boolean ──────────────────────────────────────────────────── 2 passed, 2 failed ``` MRE files: - `reproduce.ts` — calls `loadOpenAPISubgraph` directly for each spec - `specs/control.yaml` — standard `$ref`, passes (baseline) - `specs/id-based-ref.yaml` — `$id` URI as `$ref` target, fails - `specs/anchor-ref.yaml` — `$anchor` + `$id#anchor` pattern, fails - `specs/ref-sibling-keywords.yaml` — `$ref` with sibling keywords, passes **Expected behavior** When a `$ref` value matches a `$id` declared elsewhere in the same document, `dereferenceObject` should resolve it against that schema rather than treating it as a file path. Similarly, fragment references like `$ref: /schemas/details#details_id` should look up `details_id` as an `$anchor`, not as a JSON Pointer. **Environment:** - OS: macOS (darwin 25.3.0) - `@omnigraph/openapi`: 0.109.36 - `json-machete`: 0.97.6 - NodeJS: 25.x **Additional context** These aren't contrived edge cases; they come directly from the Petstore 3.1 spec maintained by the Swagger team. The `$id`/`$anchor` patterns are standard JSON Schema 2020-12 (§8.2.1, §8.2.2) and part of what OpenAPI 3.1 adopted when it aligned with JSON Schema. From reading the `json-machete` source, it looks like `dereferenceObject` would need to index `$id` declarations during traversal and check them before falling through to file/URL resolution. Happy to discuss further or help with a PR if that'd be useful.
关闭于 2026-03-20 3 条评论