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

Support for converting patternProperties? #19

Open
jehy opened this issue Jan 11, 2019 · 15 comments
Open

Support for converting patternProperties? #19

jehy opened this issue Jan 11, 2019 · 15 comments

Comments

@jehy
Copy link

jehy commented Jan 11, 2019

Hi! Great package! I'd like to know if there are plans to support JSON Schema draft-07.
I really dream abount converting ajv schemas to swagger specifications : )

@MikeRalphson
Copy link
Contributor

Are there any specific draft-07 features you need, maybe in priority order? Then we can see which ones are representable in draft-04/05 constructs.

@jehy
Copy link
Author

jehy commented Jan 11, 2019

I just checked specifications of draft-06 and draft-07 - and it seems that needed features were implemented even ealier...

I don't know what exactly works but what I need:

  1. Using nested schemas instead of refs. OpenApi does not allow this and instead requires refs to be specified - but refs can be auto generated on conversion...
  2. Support for arrays with items like
      "timingsCombined": {
         "type": "array",
         "items": {
            "searchId": {
               "type": "string",
               "maxLength": 36,
               "minLength": 36
            },
            "timings": {
               "type": "array",
               "items": {
                  "type": "object",
                  "properties": {
                     "start": {
                        "type": "integer"
                     },
                     "timings": {
                        "type": "array",
                        "items": {
                           "type": "integer"
                        }
                     }
                  },
                  "additionalProperties": false
               }
            }
         }
      },

Seems like it is also not supported by openapi.

  1. Support for patternProperties as hashes, like
      "rates": {
         "type": "object",
         "patternProperties": {
            "^[A-Z]{6}$": {
               "type": "string"
            }
         },
         "additionalProperties": false
      },

@jehy
Copy link
Author

jehy commented Jan 11, 2019

I can also provide a sample of schema that I want to convert.

@MikeRalphson
Copy link
Contributor

If I understand you right, OpenAPI does support "nested schemas" without $refs absolutely fine.

It also supports objects within array:items, but you are missing a type: object and a properties wrapper I think.

patternProperties is hard, and can really only be converted into additionalProperties (and an anyOf if additionalProperties already exists).

If you could share a gist of the schema you want to convert (rather than pasting it here), then, yes, that would be helpful.

@jehy
Copy link
Author

jehy commented Jan 13, 2019

Thanks for the explanation!
I want to make a convertor which could help use ajv schemas for swagger documentation, this is a sample of my code:
https://github.com/jehy/jsonSchemaToOpenApi/blob/master/index.js

My test schema for ajv (JSONSchema draft-07):
https://github.com/jehy/jsonSchemaToOpenApi/blob/master/searchResultV2.js

I validated it using several online validators and ajv - I think that it fine.
After validation I convert it to openapi and add as a response schema to swagger doc:
https://github.com/jehy/jsonSchemaToOpenApi/blob/master/swagger.json

Then I validate this schema using online swagger editor and openapi-schema-validator.
Several sub schemas are lost and there is a tonn of errors:
https://travis-ci.org/jehy/jsonSchemaToOpenApi/jobs/479026367

I think that the most important problem is the absense of patternProperties. May be there is a way to somehow represent it?

@MikeRalphson
Copy link
Contributor

I've got no way of validating https://github.com/jehy/jsonSchemaToOpenApi/blob/master/searchResultV2.js because it's js code not a schema document. If you have it as a plain JSON Schema document, please post a gist to that too.

As above:

patternProperties is hard, and can really only be converted into additionalProperties (and an anyOf if additionalProperties already exists).

@jehy
Copy link
Author

jehy commented Jan 14, 2019

No problem, it just needs to be serilized:
https://github.com/jehy/jsonSchemaToOpenApi/blob/master/jsonSchema.json

@MikeRalphson
Copy link
Contributor

MikeRalphson commented Jan 14, 2019

Thanks - confirmed that seems to be valid against Draft 07. Hmm, in the code patternProperties should be getting renamed to x-patternProperties, are you up to date, and still not seeing this?

@jehy
Copy link
Author

jehy commented Jan 14, 2019

I changed patternProperties to x-patternProperties. I suppose that json-schema-to-openapi-schema should do it automatically but it was not the case and I had to manually do it. It just a simple replace of key name, yeah?

The schema looks like this now:
https://gist.github.com/jehy/acfbba3fbdac9fb25eb6def324bb63ec

OpenApi validator even has no warning and errors, but it seems that's because x-patternProperties are ignored and parsed as text. Swagger shows it like this:
image

@jehy jehy changed the title Support for draft-07? Support for converting patternProperties? Jan 14, 2019
@jehy
Copy link
Author

jehy commented Jan 14, 2019

May be we can try downgrading patternProperties to additionalProperties with string type like described here?

https://www.e-learn.cn/content/wangluowenzhang/1657225

I think that we will lose regexp format, but retain the structure of document.

@MikeRalphson
Copy link
Contributor

Because patternProperties can have multiple keys, and additionalProperties may also exist (and not be a boolean type), I would still favour creating an anyOf within additionalProperties. If the anyOf ends up only having one element, it can of course be simplified. Though this would be valid Draft 05 schema, I don't know how many of the popular tools would render/validate this correctly today.

@jehy
Copy link
Author

jehy commented Jan 15, 2019

I made a simple converter for the case when we have no additionalProperties and just one patternProperties. I think that it's the most common scenario and it could be added as an option.

Code is very simple:

function isPrimitive(test) {
  return (test !== Object(test));
}

function fixPatternProperties(obj)
{
  const defaultValue = obj instanceof Array && [] || {};
  return Object.entries(obj).reduce((res, [name, value])=>{
    if(name==='additionalProperties')
    {
      if(!res.additionalProperties)
      {
        res.additionalProperties = value;
      }
      return res;
    }
    if(name==='patternProperties')
    {
      const inner = fixPatternProperties(Object.values(value)[0]);
      res.additionalProperties = inner;
      res['x-pattern'] = Object.keys(value)[0];
      return res;
    }
    if(isPrimitive(value))
    {
      res[name]=value;
      return res;
    }
    res[name]=fixPatternProperties(value);
    return res;
  }, defaultValue)
}

With this, I managed to turn https://github.com/jehy/jsonSchemaToOpenApi/blob/master/jsonSchema.json into https://github.com/jehy/jsonSchemaToOpenApi/blob/master/swagger.json - and it renders in Swagger editor beautufully, without any errors, and with all the structure and examples:
image

Full code is here if needed: https://github.com/jehy/jsonSchemaToOpenApi/blob/master/index.js

@MikeRalphson
Copy link
Contributor

Thanks. I think we would need to cope with more cases, but I like the method of preserving the pattern(s). Good idea!

@medfreeman
Copy link

@MikeRalphson
Which cases would you like to see implemented ?
I'd like to submit a PR as i'm depending on this feature and currently implemented it on a personal library following @jehy 's code.

@MikeRalphson
Copy link
Contributor

The cases would be where additionalProperties already exists, as either a boolean or an object.

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

3 participants