Skip to content

Add json-schema support #118

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

Draft
wants to merge 6 commits into
base: 4.x
Choose a base branch
from
Draft

Add json-schema support #118

wants to merge 6 commits into from

Conversation

kerwanp
Copy link

@kerwanp kerwanp commented Jul 5, 2025

πŸ”— Linked issue

❓ Type of change

  • ✨ New feature (a non-breaking change that adds functionality)

πŸ“š Description

This feature adds the ability to transform validators to json-schema using the toJSONSchema method.

This will open a lot of doors for libraries that can build around the json-schema standards (openapi generation, form builder, configuration files, etc).

Implementation

This is currently a draft and serves as an implementation proposal.

The json-schema is generated during the schema validation, allowing the user to retrieve it using toJSONSchema.

const validator = vine.compile(vine.object({
   hello: vine.string(),
}))

const schema = validator.toJSONSchema()

assert.toDeepEqual(schema, {
  type: 'object',
  properties: {
    hello: { type: 'string' }
  },
  required: ['hello']
})

All ConstructableSchema[PARSE] method must also return the a JSONSchemaV7. This is used to build the root of the schema. (e.g https://github.com/kerwanp/vine/blob/4.x/src/schema/base/literal.ts#L583-L583)

When creating rules, it is possible to pass an optional parameter for altering the json-schema.

export const emailRule = createRule<EmailOptions | undefined>(
  function email(value, options, field) {
    if (!helpers.isEmail(value as string, options)) {
      field.report(messages.email, 'email', field)
    }
  },
  {
    json: (schema) => {
      schema.format = 'email'
    },
  }
)

The user is able to provide custom meta that will be merged with the schema to provide custom parameters.

vine.string().meta({ description: "Hello world" })

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@thetutlage
Copy link
Contributor

Hello @kerwanp

The high-level approach looks fine to me. However, I will have a few changes.

  • I will rename the json property on a rule to toJSONSchema. Which indicates, this method will be called when converting the Vine schema node to a JSON schema node.
  • Similarly, the protected method on the Vine schema classes should be called toJSONSchema.
  • Finally, the meta property should not be strictly tied to JSON schema. If we want to do it, we should rename it to toJSONSchema. It will accept either a JSON schema object, or a function.

Also, once we merge this PR, Vine will support JSON schema as a first-class citizen and all custom schema types must implement the toJSONSchema method as-well.

@thetutlage
Copy link
Contributor

Also, we should write some tests for the vine.group and vine.union schema types as well πŸ‘

@kerwanp
Copy link
Author

kerwanp commented Jul 7, 2025

Thanks for the feedback!

I added support for vine.group, vine.literal, vine.union and vine.unionOfTypes.

Concerning the meta method. We can either change this to be more generic allowing to retrieve the provided meta when using toJSON() which would be also merged with the json-schema or we could make it specific to json schema (with a different method name). What do you prefer?

I also started the implementation of integration tests that validate values against the generate json-schema using ajv. This can help use spot issues with the complexity of some generated schemas (tuples, records, etc). What do you think?

I we are good with the implementation I will start expanding the test cases, cleaning up my work and add some comments

@thetutlage
Copy link
Contributor

I also started the implementation of integration tests that validate values against the generate json-schema using ajv. This can help use spot issues with the complexity of some generated schemas (tuples, records, etc). What do you think?

Yeah, this seems like a great strategy.

Concerning the meta method. We can either change this to be more generic allowing to retrieve the provided meta when using toJSON() which would be also merged with the json-schema or we could make it specific to json schema (with a different method name). What do you prefer?

I will be okay with a more generic approach. However, the issue is, how do we know which properties to merge with the JSON schema?

@kerwanp
Copy link
Author

kerwanp commented Jul 13, 2025

I will be okay with a more generic approach. However, the issue is, how do we know which properties to merge with the JSON schema?

LIbraries like Zod provide a meta method that accept anything with a set of known properties that will be merged (title, description, examples, etc). This set is really restrictive and does not really allow schema customization. We can for the moment just rely on JSONSchema as it covers most of the use case. We could rename the method to json or jsonSchema and if metadata is a asked feature the current implementation could be extended

@thetutlage
Copy link
Contributor

We could rename the method to json or jsonSchema and if metadata is a asked feature the current implementation could be extended

Cool, let's go with that. Maybe people can rely on the JSONschema properties for their other needs as well.

@thetutlage
Copy link
Contributor

@kerwanp What are the next steps for this PR? Do you need any feedback from me?

@kerwanp
Copy link
Author

kerwanp commented Jul 31, 2025

@kerwanp What are the next steps for this PR? Do you need any feedback from me?

Hi, I am currently in vacations, will be back the 8th to finish this PR and I think I have all the information required

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.

2 participants