vitalics / ajv-ts

First-class ajv typescript JSON-schema builder inspired from Zod
https://www.npmjs.com/package/ajv-ts
MIT License
39 stars 1 forks source link

[feature] add support for generating schemas from JSON/objects of JSON schema #31

Closed miguelrk closed 7 months ago

miguelrk commented 7 months ago

Is your feature request related to a problem? Please describe. One of the major benefits of using JSON Schema in contrast to libraries like zod, is that JSON schema is serializable, and thus, it's easy to persist in a database and expose via an API. What's missing (at least I couldn't find it) is a way to generate ajv-ts schemas at runtime from this serialized JSON schemas (coming from a database or an API, or even a file).

Describe the solution you'd like A utility function (e.g. parseSchema, fromJSONSchema, or similar) to generate a schema from a serialized representation of the JSON schema definition would be great. It could look something like the following:

import { parseSchema } from "ajv-ts";

const MyJsonSchema = {
  "title": "Example Schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "description": "Age in years",
      "type": "integer",
      "minimum": 0
    },
  },
  "required": ["name", "age"]
}

// creating a schema from the JSON schema object
const mySchema = parseSchema(MyJsonSchema); // usage of "mySchema" is the same

What do you think? Is this even possible with the current implementation? How complex might it be to add a feature like this? I do see it has very valid use cases...

Describe alternatives you've considered Alternatively, one could use online tools likeJSON to Zod Tool or a library like json-schema-to-zod, however, they both have the issue that zod is not 100% JSON-schema compatible, so there might be some "information-loss". On the other hand, if ajv-ts is 100% JSON schema compatible then we don't have this issue anymore.


In any case, this library is great! Congrats @vitalics, I'm glad I found it. I stumbled with ajv-ts after looking for solutions to the problem above and reading the blogpost. ajv-ts was a great idea! It solves the shortcommings of zod, while using its strengths (great API for developers), and all while aligning to the JSON schema standard 💯

vitalics commented 7 months ago

Hi, @miguelrk It can be possible, but I suppose that this function looses DevEx, since schema parsing in types while on-fly autocompletion can take the TS server a longer time to respond.

However, as an alternative, we can provide API with generic:

import s from "ajv-ts";

const MyJsonSchema = {
  "title": "Example Schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "description": "Age in years",
      "type": "integer",
      "minimum": 0
    },
  },
  "required": ["name", "age"]
}

// creating a schema from the JSON schema object
type MyObjectFromSchema = {
  name: string,
  age: number,
}
const mySchema = s.fromSchema<MyObjectFromSchema>(MyJsonSchema); 

mySchema.safeParse({})

For now, as a workaround, you can define the next schema(with type looseness):

import s from 'ajv-ts'

const MyJsonSchema = {
  "title": "Example Schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "description": "Age in years",
      "type": "integer",
      "minimum": 0
    },
  },
  "required": ["name", "age"]
}

const mySchema = s.any()
mySchema.schema = MyJsonSchema

mySchema.safeParse() // will works
miguelrk commented 7 months ago

Again, thanks for the quick and thorough response! I'm no typescript wizard, so I wouldn't have figured that one out 💯

Your first proposal requires defining a JSON schema, and also a TypeScript type, while the second example requires only the JSON schema, but loses types. I understand that due to TS being too slow, my approach would be a no go, but if I understood correctly, would what you propose achieve the same?

Ideally, one could supply only a JSON schema and not have to supply the typescript type as well. Maybe the first alternative you propose using generics could leveaage someting like json-schema-to-typescript or json-schema-to-ts to automatically handle this? Although I'm not certain if adding the extra dependencies is worth it and if having it built-in is out of scope for ajv-ts. That being said, I do feel that the main benefit of this library over zod is that the JSON schemas are easily serializable, that ma. Happy to hear your thoughts on this

vitalics commented 7 months ago

extra dependencies will breaks the idea of the ajv-ts library. Transforming the JSON-schema to typescript adds extra complexity and move focus from validation and building to transformation. I'll close this issue for now. If maintainers will see the sense in generation - I'll open this issue again as feature request.