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

defer resolution of references #415

Open
ahl opened this issue Sep 29, 2023 · 0 comments
Open

defer resolution of references #415

ahl opened this issue Sep 29, 2023 · 0 comments

Comments

@ahl
Copy link
Collaborator

ahl commented Sep 29, 2023

As of #405 the handling of subschemas has changed significantly. In particular, we try to resolve and merge subschemas in order to produce better, higher fidelity data types. We resolve references in order to--for example--merge types. This, however, opens the door to infinite recursion if we follow references around cyclic types. Here's a trivial (and extremely painful to get right) schema that demonstrates the problem:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "a": {
      "type": "object",
      "properties": {
        "other": {
          "$ref": "#/definitions/b"
        }
      }
    },
    "b": {
      "type": "object",
      "properties": {
        "other": {
          "$ref": "#/definitions/a"
        }
      }
    },
    "ab": {
      "allOf": [
        {
          "$ref": "#/definitions/a"
        },
        {
          "$ref": "#/definitions/b"
        }
      ]
    }
  }
}

There are many other types of cycles we can fall into, but I believe we can significantly ameliorate the problem (and perhaps solve it entirely) by taking a couple of steps:

1. Defer resolution of references as late as possible.

There are two top-level schema structures that we need to process before we can start type conversion/inference: allOf and anyOf (the former we do today; the latter we do not). We have some sort of handling of all other structures, but those need work. I'm going to focus exclusively on allOf here; for anyOf see #414 since that can become more or less a special case.

We eagerly merge schemas which includes resolving references. In part we do this to know what merged schemas are valid. But we can be lazier about that! A top-level allOf that's not valid? That means the schema specified a type or dependency that was never going to valid... in which case it's fine to generate a type that could never be valid!

2. Introduce a new type of dependency

The input schema contains dependencies; we could add our own type of dependency that is based on content rather than names. In the example above we could start to generate the type for ab and say: make a placeholder for { allOf: [a, b] } and when in the next step we tried to resolve the property other we would see that it's type needed to be a reference. This would assume some sort of canonical representation or flexible matching such that { allOf: [a, b] } was equivalent to { allOf: [b, a] }.

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

No branches or pull requests

1 participant