GithubHelp home page GithubHelp logo

joi-to-json-schema's Introduction

joi-to-json-schema

The goal is to provide best effort conversion from Joi objects to JSON Schema (draft-04) with the understanding that only some of Joi's schematics can be converted directly. Primarily this module exists to convert Joi schema objects for existing tools which happen to currently consume JSON Schema.

npm version Build Status Dependencies Status DevDependencies Status

NPM NPM

Installation

npm install joi-to-json-schema

Usage

var joi = require('joi'),
    convert = require('joi-to-json-schema'),
    joiSchema = joi.object({
      'name': joi.string().required().regex(/^\w+$/),
      'description': joi.string().optional().default('no description provided'),
      'a': joi.boolean().required().default(false),
      'b': joi.alternatives().when('a', {
        is: true,
        then: joi.string().default('a is true'),
        otherwise: joi.number().default(0)
      })
    });

convert(joiSchema);

which will produce:

{ type: 'object',
  properties: 
   { name: { type: 'string', pattern: '^\\w+$' },
     description: { default: 'no description provided', type: 'string' },
     a: { type: 'boolean', default: false },
     b: { oneOf: [ { default: 'a is true', type: 'string' }, { type: 'number', default: 0 } ] } },
  additionalProperties: false,
  required: [ 'name', 'a' ] }

JSDOC

 /**
  * Converts the supplied joi validation object into a JSON schema object,
  * optionally applying a transformation.
  *
  * @param {JoiValidation} joi
  * @param {TransformFunction} [transformer=null]
  * @returns {JSONSchema}
  */
 export default function convert(joi,transformer=null) {
   // ...
 };

 /**
  * Joi Validation Object
  * @typedef {object} JoiValidation
  */

 /**
  * Transformation Function - applied just before `convert()` returns and called as `function(object):object`
  * @typedef {function} TransformFunction
  */

 /**
  * JSON Schema Object
  * @typedef {object} JSONSchema
  */

Notes

Joi's conditional form, i.e. .when('name',{is:cond,then:joi,otherwise:joi}), is evaluated at runtime and since, from the perspective of the schema, there is no way of knowing what the condition might resolve to, this module takes the position that it should provide all possible resolutions in a JSON Schema oneOf:[] clause.

Testing

All tests cases are first checked against expected results and then validated using Kris Zyp's excellent json-schema

References

LICENSE

Copyright 2014, Mozilla Foundation

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

joi-to-json-schema's People

Contributors

andresmeidla avatar bbb avatar jdpnielsen avatar jessepinho avatar kenspirit avatar lbdremy avatar lightsofapollo avatar mooyoul avatar philikon avatar raisch avatar ratson avatar shaheenp avatar simlu avatar syzer avatar yotamberk avatar zaaack avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

joi-to-json-schema's Issues

Joi when require is

I have a problem with Joi When usage.

the when must be use with 2 cases :

  • Directly with other object field
  • With specific Joi schema

The problem with the second type. For example I have this schema :

Joi.when(Joi.object({ type : 'model' }).unknown(), {
    then        : Joi.object().keys(modelObject),
    otherwise   : Joi.object().keys(mathObject),
})

This schema switch full result schema when one specific field has specific value.

In my case, I can't use the is option but your library force this option and ignore the second when use case.

If I comment this part it works fine :

if (!match.is) {
throw new Error('joi.when requires an "is"');
}

joi.when requires an "is"

The following seems to fall to convert:

const geoRectangle = {
  type: Joi.string()
    .valid('rectangle')
    .required(),
  geometry: {
    nw: Joi.object(geoPoint).required(),
    se: Joi.object(geoPoint).required()
  }
};

const geoPolygon = {
  type: Joi.string()
    .valid('polygon')
    .required(),
  geometry: {
    points: Joi.array()
      .min(3)
      .items(Joi.object(geoPoint))
  }
};

const geoShape = Joi.object()
  .when(Joi.object({ type: geoPolygon.type }), {
    then: Joi.object(geoPolygon)
  })
  .when(Joi.object({ type: geoRectangle.type }), {
    then: Joi.object(geoRectangle)
  })

fails with joi.when requires an "is"

Disabling the check for is converts things as expected, so thats nice.

I see https://github.com/lightsofapollo/joi-to-json-schema/blob/master/test/transformer_test.js#L79 does not cover the structure i wrote.

Can you add documentation and other annotations?

Is it possible to do something like this?

foo: joi.string().meta({title: "Foo", description: "This is a foo", "x-myattribute": true})

// convert into:
foo: 
  type: 'string'
  title: 'Foo' 
  description: 'This is a foo'
  x-myattribute: true

I want to use title, description, and custom annotations for openapi via joi-to-openapi-definition.

Bump [email protected]

Hi,

Joi released a new version two weeks ago (9.0.0). It might be time to update joi-to-json-schema dependency. I think there's gonna be incompatibilities (we ran into a few issues with model label ourselves).

I got some time to look into it this week. Is it worth the effort?

[Object object] instead of regex in output when using joi 10.2.2

From the README.md example, modified to include console.log:

var joi = require('joi'),
    convert = require('joi-to-json-schema'),
    joiSchema = joi.object({
      'name': joi.string().required().regex(/^\w+$/),
      'description': joi.string().optional().default('no description provided'),
      'a': joi.boolean().required().default(false),
      'b': joi.alternatives().when('a', {
        is: true,
        then: joi.string().default('a is true'),
        otherwise: joi.number().default(0)
      })
    });

console.log(convert(joiSchema));

Expected:

{ type: 'object',
  properties: 
   { name: { type: 'string', pattern: '^\\w+$' },
     description: { default: 'no description provided', type: 'string' },
     a: { type: 'boolean', default: false },
     b: { oneOf: [ { default: 'a is true', type: 'string' }, { type: 'number', default: 0 } ] } },
  additionalProperties: false,
  required: [ 'name', 'a' ] }

Actual:

{ type: 'object',
  properties: 
   { name: { type: 'string', pattern: '[object Object]' },
     description: { default: 'no description provided', type: 'string' },
     a: { default: false, type: 'boolean' },
     b: { oneOf: [Object] } },
  additionalProperties: true,
  patterns: [],
  required: [ 'name', 'a' ] }

How to create const?

Seem's there is no support for const type in schema? I create following joi rule with only one valid value:

myfield: Joi.equal('Ingredient').required()

Now this is generated:

        "myfield": {
            "enum": [
                "Ingredient"
            ]
        }

What I would like to see:

        "myfield": {
            "const":  "Ingredient"
        }

Could this be doable?

supporting draft-07?

what would it take to support json schema draft-07?

if nothing else I would be interested in adding support for it.

Developing is broken in node6 due to some fs dependency

mbroadst@retinoid:joi-to-json-schema (master=)$ npm install

> [email protected] prepublish /Users/mbroadst/Development/node/joi-to-json-schema
> npm run build


> [email protected] build /Users/mbroadst/Development/node/joi-to-json-schema
> 6to5 -s -e src --out-dir build

(node) v8::ObjectTemplate::Set() with non-primitive values is deprecated
(node) and will stop working in the next major release.

==== JS stack trace =========================================

Security context: 0x2519ebfc9fa9 <JS Object>#0#
    1: .node [module.js:568] [pc=0x320800ec17c4] (this=0x1aa74dfce091 <an Object with map 0x2e4379517e49>#1#,module=0x153b64214089 <a Module with map 0x2e4379518421>#2#,filename=0x153b64214061 <String[96]: /Users/mbroadst/Development/node/joi-to-json-schema/node_modules/fsevents/build/Release/fse.node>)
    2: load [module.js:456] [pc=0x320800d39152] (this=0x153b64214089 <a Module with map 0x2e4379518421>#2#,filename=0x153b64214061 <String[96]: /Users/mbroadst/Development/node/joi-to-json-schema/node_modules/fsevents/build/Release/fse.node>)
    3: tryModuleLoad(aka tryModuleLoad) [module.js:415] [pc=0x320800d38c7d] (this=0x2519ebf04189 <undefined>,module=0x153b64214089 <a Module with map 0x2e4379518421>#2#,filename=0x153b64214061 <String[96]: /Users/mbroadst/Development/node/joi-to-json-schema/node_modules/fsevents/build/Release/fse.node>)
    4: _load [module.js:407] [pc=0x320800d348c2] (this=0x1aa74dfce111 <JS Function Module (SharedFunctionInfo 0x1aa74df22f31)>#3#,request=0x3e8d83165171 <String[19]: ./build/Release/fse>,parent=0x153b6420e4d1 <a Module with map 0x2e4379518421>#4#,isMain=0x2519ebf04299 <false>)
n-schema/node_modules/fsevents/fsevents.js>,__dirname=0x153b64212769 <String[73]: /Users/mbroadst/Development/node/joi-to-json-schema/node_modules/fsevents>)
b64204629 <an Object with map 0x88f74907bc9>#9#,require=0x153b642095f1 <JS Function require (SharedFunctionInfo 0x1aa74df542b1)>#10#,module=0x153b642045d9 <a Module with map 0x2e4379518421>#8#,__filename=0x153b642045b1 <String[97]: /Users/mbroadst/Development/node/joi-to-json-schema/node_modules/chokidar/lib/fsevents-handler.js>,__dirname=0x153b64209589 <String[77]: /Users/mbroadst/Development/node/joi-to-json-schema/node_modules/chokidar/lib>)
  22: require(aka require) [internal/module.js:20] [pc=0x320800d427c6] (this=0x2519ebf04189 <undefined>,path=0x3e8d83145b19 <String[18]: ./fsevents-handler>)
#,request=0x3e8d8313bb69 <String[8]: chokidar>,parent=0x153b6417ceb9 <a Module with map 0x2e4379518421>#16#,isMain=0x2519ebf04299 <false>)
 map 0x2e4379518421>#16#,filename=0x153b6417ce91 <String[85]: /Users/mbroadst/Development/node/joi-to-json-schema/node_modules/6to5/bin/6to5/dir.js>)

 1: v8::Template::Set(v8::Local<v8::Name>, v8::Local<v8::Data>, v8::PropertyAttribute)
 2: fse::FSEvents::Initialize(v8::Local<v8::Object>)
 3: node::DLOpen(v8::FunctionCallbackInfo<v8::Value> const&)
 4: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&))
 5: v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)1>)
 6: v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*)
 7: 0x320800c0961b
Segmentation fault: 11

joi forbidden() being ignored

converting

joi.object({
  'string': joi.string(),
  'required string': joi.string().required(),
  'forbidden string': joi.string().forbidden()
});

produces:

{
  "type": "object",
  "properties": {
    "string": {
      "type": "string"
    },
    "required string": {
      "type": "string"
    },
    "forbidden string": {  <== INCORRECT
      "type": "string"
    }
  },
  "additionalProperties": false,
  "required": [
    "required string"
  ]
}

rather than:

{
  "type": "object",
  "properties": {
    "string": {
      "type": "string"
    },
    "required string": {
      "type": "string"
    }
  },
  "additionalProperties": false,
  "required": [
    "required string"
  ]
}

which is particularly troublesome when using joi.alternatives().

Joi 1.16 update : Error: requires a joi schema object

While trying to convert my joi schema to JSON I got an error : AssertionError [ERR_ASSERTION]: requires a joi schema object

Here is my code :

import * as Joi from "@hapi/joi";

const convert = require("joi-to-json-schema");

const  report = Joi.object({
      part: Joi.string()
          .valid(['a', 'b', 'c'])
          .required(),
     })

convert(report);

This seems to be related to hapijs/joi#1834

We should use Joi.isSchema() instead.

I will try to provide a PR using isSchema when available then fallback to isJoi if it's OK for you.

joi.string().iso() โ†’ format: 'uri'

The result for joi.string().uri() should be { type: 'string', format: 'uri' }, rhyming with how you handle joi.date().iso():

> var joi = require('joi'), convert = require('joi-to-json-schema'); convert(joi.date().iso())
{ type: 'string', format: 'date-time' }
> var joi = require('joi'), convert = require('joi-to-json-schema'); convert(joi.string().uri())
{ type: 'string' }

Support `Joi.date().timestamp()` schema

Currently, joi-to-json-schema converts Joi.date().timestamp() schema to date-time formatted string type.
but actually Joi.date().timestamp() schema validates unix timestamp (sec based) or javascript timestamp (ms based), which is actual type is integer.

Doesn't include extensions?

I have added the joi-phone-number-extensions plugin and am receiving an error "Error: sorry, do not know how to convert unknown joi type: "phoneNumber". Rather then making my entire schema unable to parse, what can be done here?

Convert percision() to use multipleOf

When I declare a number in joi:
Joi.number().precision(0.1).min(0).max(10)
The JSON schema should limit the allowed number to multiples of 0.1 with multiOf to not allow numbers like 1.00001

@yotamberk

uuid format

Hi. Could you also add uuid format support?
Example:

joi
  .string()
  .guid({
    version: [
      'uuidv1'
    ]
  })
  .required();

let eventSchema = {
  startTime: eventStartTimeSchema
};

should convert to

{ type: 'object',
  properties: { startTime: { type: 'string', format: 'uuid' } },
  additionalProperties: false,
  patterns: [],
  required: [ 'startTime' ] }

Travis-ci?

James, could you setup a travis-ci.org for this repo so the banner I added to the (newly updated) README will work? I'm unable to do this myself as I'm not the owner. Thanks.

Using `joi.allow()` generates an `enum` when it shouldn't

Given the joi object

Joi.string().example('MR').description('civility').allow('')

It mistakingly returns

"civility": {
  "description": "civility",
  "enum": [ "" ], 
  "type": "string"
}

While it should return something like

"civility": {
  "description": "civility",
  "type": "string"
}

Indeed, as stated in the joi.allow() API: this whitelist of allowed values is in addition to any other permitted values

Show Whitelist for valid()

Is there a way to list all values given by joi.string().valid([..., ...]) ?

What I want to do:

/// My controller
const validColors = ["BLUE", "RED", "GREEN"];

const schema = joi.object({
  colors: joi.string().valid(validColors)
});

/// In my test file
const schema = myControler.schema; // joi schema
const joiConverter = require("joi-to-json-schema");

test("Colors must be contained in valid colors", () => {
  const validationSchema = joiConverter(schema);

  const validColors = ["BLUE", "RED", "GREEN", "OTHER"];
  expect(validationSchema.???).toContain(validColors);
});

I expect something (in place of .???) to test the whitelist I gave in my controler.

Swagger failed to load after using joi lazy(fn)

Using JOI validation with lazy(fn) to check recursive validation. In this case swagger failed to load routes even all routes are working. Below are all the generated logs.

Failed to build API documentation for "/Demo"!
This is likely a bug in your Foxx service.
Check the route methods you are using to document your API. via Error: sorry, do not know how to convert unknown joi type: "lazy"
at convert (/usr/share/arangodb3/js/node/node_modules/joi-to-json-schema/build/index.js:186:11)
at Array.forEach (native)
at Object.array (/usr/share/arangodb3/js/node/node_modules/joi-to-json-schema/build/index.js:87:14)
at convert (/usr/share/arangodb3/js/node/node_modules/joi-to-json-schema/build/index.js:225:32)
at /usr/share/arangodb3/js/node/node_modules/joi-to-json-schema/build/index.js:167:43
at Array.forEach (native)
at Object.object (/usr/share/arangodb3/js/node/node_modules/joi-to-json-schema/build/index.js:165:25)
at joi2schema (/usr/share/arangodb3/js/server/modules/@arangodb/foxx/router/swagger-context.js:568:10)

i already had opened this issue on github ArangoDB issues
arangodb/arangodb#6132

what's the trick to excluding default functions?

If I have a joi schema like this:

joi.object().keys({
foo: joi.string().default('foo'),
bar: joi.string().default('bar'),
created: joi.date().default(Date.now, 'generated'),
updated: joi.date().default(Date.now, 'generated')
})

And I don't want the function defaults to come through into the json schema export, but I do want the static defaults, how do I achieve that?

By just calling convert(schema) by default I get this:

{
type: 'object',
properties: {
foo: { default: 'foo', type: 'string' },
bar: { default: 'bar', type: 'string' },
created: { default: [Object], type: 'string', format: 'date-time' },
updated: { default: [Object], type: 'string', format: 'date-time' },
},
additionalProperties: false
}

That [Object] is the Date.now function

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.