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

enum type without specifying values #340

Closed
swamikevala opened this issue Jul 28, 2017 · 9 comments
Closed

enum type without specifying values #340

swamikevala opened this issue Jul 28, 2017 · 9 comments
Milestone

Comments

@swamikevala
Copy link

swamikevala commented Jul 28, 2017

I want to define a property as an enum. But I don't want to enter the enum values in the schema. The values will be fetched from a database and will be dynamic in nature.

I want to do something like this:

"TAG": { "type": "enum" }

The schema will be used to auto-generate api code and database queries. (So I need to know that it is an enum property - so the generated code will query the constants table in the db). What is the best way to do this?

I'm currenty followung the openAPI spec, so I'm doing this right now (using a custom extension) :

properties: {
 ...
},
"x-enums": [ "GENDER", "TAG", "COUNTRY" ]
@handrews
Copy link
Contributor

I think that what you want could be accomplished via the $data proposal #51 where the literal values are loaded from an instance document. You would fetch the instance document from the database.

Alternatively, you can just dynamically generate the schema based on the current table contents, which would be a workable solution right now.

@swamikevala
Copy link
Author

swamikevala commented Jul 29, 2017

I want to use the schema to generate a scaffolding for my front and back end code and possibly to define some of my database objects. So the schema will come first, and then the database after.
I just want a way to mention that the values will be from an enumerated list - but I don't want to specify that list at the time of writing the schema

@jdesrosiers
Copy link
Member

jdesrosiers commented Jul 30, 2017

@swamikevala, I like your schema-first approach! I have the same philosophy (although I'm not a huge fan of scaffolding).

Anyway, I don't think there is a good answer to your particular problem. Ideally, you probably want to be able to do something like the following where "/countries" is an endpoint that points to an array of enum options. That URI doesn't have to point anything real. It's just a hint for your scaffolding generator.

{
  "country": {
    "enum": { "$ref": "/countries" }
  }
}

This would allow you to indicate that you expect an enum while differing defining the values of that enum. Unfortunately, you can only $ref a JSON Schema, not arbitrary data. The best you can do is this.

{
  "country": { "$ref": "/countries" }
}

Then have "/countries" be a schema that defines an enum. But, that doesn't solve your problem because you lose any indication that this will be an enum one day.

The $data proposal that @handrews mentioned could solve that problem. $data is like a $ref for data. It is intended for referring to the data that the schema is validating, but you could just as easily reference another document by using a URI instead of #. It would look like this.

{
  "country": {
    "enum": { "$data": "/countries" }
  }
}

I think that would solve your problem. Unfortunately, $data is just a proposal and I don't think one that is likely to be accepted.

So, I think your only option is to introduce a custom keyword to solve your problem. Or, maybe there is another way to design your solution where something like this isn't needed.

@swamikevala
Copy link
Author

swamikevala commented Jul 30, 2017

@jdesrosiers, thanks for the detailed response. I had considered all those options. I would like to be able to use the first option. i.e. Allow $ref to point to arbitrary json data (not necessarily a json schema). In my opinion that would be the simplest and clearest approach.

Do you think this could be something we could request for the next version of the spec, or is there a good reason for not allowing this?

I guess we'll go with our custom "x-enums" keyword. This also will give us more flexibility (e.g. for hierarchical enums)

"x-enums": { 
          "GENDER": { "key": "gender" }, 
          "NATIONALITY": { "key": "country.iso2" },
          "COUNTRY": { "key": "country.iso2" },
          "STATE": { 
            "key": "state",
            "parentEnum": "COUNTRY"
          }

@epoberezkin
Copy link
Member

This is another proposal to achieve it: https://github.com/json-schema-org/json-schema-spec/issues/322

@jdesrosiers
Copy link
Member

Do you think this could be something we could request for the next version of the spec, or is there a good reason for not allowing this?

You can always start the conversation. But, I think it's unlikely to be accepted considering that we just decided to go the other direction on this topic. Until the most recent version of the spec (draft-06), it was not made explicit that $ref can only reference a schema. However, in practice, it has been consistently implemented that way. I don't know what the reasons are for that and I wasn't involved in the discussion where this decision was made.

Your use case (scaffolding generation) is outside the scope of what JSON Schema was designed for. In any normal use case that I have seen or can think of, using $ref for anything other than a schema is a poor design decision. It's possible that this decision was made to encourage schema authors to write better schemas while also making validator implementation easier. There might also be a more technical reason that I haven't thought of. Even tho I only use $ref for schemas, I'd be interested in getting a short summary of why this decision was made as well.

@handrews
Copy link
Contributor

I think that restricting $ref was a good idea, but that the current restriction is not necessarily perfect. For instance, I have a very strong need to allow $ref (or a keyword with similar behaviors) for LDOs in hyper-schema (see #319 ).

It makes sense to use allow referencing certain coherent units that are hard to manage otherwise- the array nature of the links keyword makes re-using any aspect of a link with an allOf somewhere between difficult and impossible.

Whether this issue brings up another good use case I'm not sure- I haven't thought it through yet. But I would encourage looking at #322 as @epoberezkin suggests as the more an idea picks up use cases from multiple people, the more likely it is to be considered.

Both $data and #322 involve expanding the scope of JSON Schema in new ways. $data is a high priority for me to resolve for the next draft, one way or the other, so it would be good to consider this as well. I'd like to not keep leaving major new direction proposals open for multiple drafts.

@handrews handrews added the $data label Aug 18, 2017
@handrews handrews added this to the draft-07 (wright-*-02) milestone Aug 18, 2017
@handrews
Copy link
Contributor

"$data" will not be decided for the next draft, so I'm moving this out as well. There is no advocate for it with enough time to move it forward right now.

@handrews handrews modified the milestones: draft-future, draft-07 (wright-*-02) Aug 30, 2017
@handrews
Copy link
Contributor

This topic is more comprehensively tracked under #855, where we have consolidated several closely related ideas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

No branches or pull requests

4 participants