ts-json-schema-generator icon indicating copy to clipboard operation
ts-json-schema-generator copied to clipboard

Can we have an escape hatch via some jsdoc annotation to insert arbitrary json-schema at a particular place?

Open homanchou opened this issue 3 years ago • 5 comments

There are some instances where json-schema allows for certain expressiveness that cannot be represented in typescript. One such need I have is an object where only one of the following properties is required.

Using something like this:

interface oneOfXYZ {
  x?: number,
  y?: number,
  z?: number  
}

Without optionals, that would require all properties to be present, and with optionals would allow all properties to be ignored.

In json-schema you could however do something like this:

"oneOfXYZ": {
   "properties": {
     "x": { "type": "number" },
     "y": { "type": "number" },
     "z": { "type": "number" },
   },
  "oneOf": [
     { "required": ["x"] },
     { "required": ["y"] },
     { "required": ["z"] }
  ]
}

What if we had the ability to inject the "oneOf" part, writing that ourselves in jsDoc, something like a heredoc that is then just placed into the output schema:

/**
* @custom  "oneOf": [
         { "required": ["x"] },
         { "required": ["y"] },
         { "required": ["z"] }
      ]
*/
interface oneOfXYZ {
  x?: number,
  y?: number,
  z?: number  
}

homanchou avatar May 29 '21 17:05 homanchou

Why don't you make a type union of three interfaces?

domoritz avatar May 29 '21 18:05 domoritz

I have similar problem. We using https://github.com/json-schema-faker to generate a mock data from a json schema. Json-schema-faker support many userfull extensions, including custom extensions. For example property "faker", with additional information for mock data generation via faker library.

But ts-json-schema-generator cut out all custom attributes, that we add to jsdoc. For example:

  /** 
  * @format datetime
  * @faker blabala
  */
  someField: string;

Results to:

       "someField": {
          "type": "string",
          "format": "datetime" // format field saved, super!
          // but where my faker field???
        }

Please, add some option to include all custom @fields that found in jsdoc comment!

PFight avatar Sep 23 '21 07:09 PFight

Follow-up regarding suggestion for "type union of interfaces".

interface MatchConfig {
  match: RegExp;
}

interface EqualConfig {
  equal: string;
}

type MatchPatternConfig = MatchConfig | EqualConfig;

export default MatchPatternConfig;

The generated schema is anyOf rather than oneOf. So, closer, but not quite there.

            "anyOf": [
              {
                "additionalProperties": false,
                "properties": {
                  "match": {
                    "format": "regex",
                    "type": "string"
                  }
                },
                "required": [
                  "match"
                ],
                "type": "object"
              },
              {
                "additionalProperties": false,
                "properties": {
                  "equal": {
                    "type": "string"
                  }
                },
                "required": [
                  "equal"
                ],
                "type": "object"
              }
            ]

kgilpin avatar Dec 02 '21 19:12 kgilpin

@kgilpin did you ever get to the bottom of this?

ThatOneAwkwardGuy avatar Feb 11 '22 23:02 ThatOneAwkwardGuy

I'd also need the ability to generate oneOf out of unions.

tobias-tengler avatar Jan 11 '23 20:01 tobias-tengler