Not able to reference object using hapi-swagger library - hapi-swagger

I am using hapi-swagger library 14.0.0. As per hapi-swagger library documentation used options.deReference = true. Still, I am not able to reference object.
Can anybody help me to solve the issue?
Expected behavior
{
"200": {
"description": "a pet to be returned",
"schema": {
"$ref": "#/definitions/Pet"
}
}
}
Getting
{
"200": {
"description": "a pet to be returned",
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
}
}

Related

Add pattern validation in json schema when property is present

Below is my schema definition and I would like to add pattern that depends on environment propertyName (env1, env2 or env3). Each env should have different pattern. For instance when env1 is present then url will have a different pattern than when env2 is present etc.
{
"environments": {
"env1": {
"defaultAccess": {
"url": [
"something-staging"
]
}
}
}
}
My current schema definition for that example
{
"$schema": "https://json-schema.org/draft-07/schema#",
"definitions": {
"envType": {
"type": "object",
"properties": {
"defaultAccess": {
"type": "object",
"properties": {
"url": {
"type": "string",
"pattern": "^[a-zA-Z0-9- \/]*$"
}
},
"required": [
"url"
]
}
}
},
"environmentTypes": {
"type": "object",
"properties": {
"env1": {
"$ref": "#/definitions/envType"
},
"env2": {
"$ref": "#/definitions/envType"
},
"env3": {
"$ref": "#/definitions/envType"
}
}
},
"type": "object",
"properties": {
"environments": {
"$ref": "#/definitions/environmentTypes"
}
}
}
}
In my head I have something like this but do not know how to apply it to the schema properly.
{
"if": {
"properties": {
"environments": {
"env1" : {}
}
}
},
"then":{
"properties": {
"environments-env1-defaultAccess-url" : { "pattern": "^((?!-env2).)*$" }
}
}
}
etc..
If understand correctly what you're trying to do, you shouldn't need conditionals for this kind of thing.
You have an error in your schema that might be tripping you up. You have your main schema inside the definitions keyword. If you run this through a validator, you should get an error saying that the value a /definitions/type must be an object.
Aside from that, schema composition using allOf should do the trick. Below, I've shown an example at /definitions/env1Type.
It looks like you were hoping for a less verbose way to specify a schema deep in an object structure (""). Unfortunately, there's no way around having to chain the properties keyword all the way down like I've demonstrated at /definitions/env1Type.
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"environments": { "$ref": "#/definitions/environmentTypes" }
},
"definitions": {
"environmentTypes": {
"type": "object",
"properties": {
"env1": { "$ref": "#/definitions/env1Type" },
"env2": { "$ref": "#/definitions/env2Type" },
"env3": { "$ref": "#/definitions/env3Type" }
}
},
"envType": { ... },
"env1Type": {
"allOf": [{ "$ref": "#/definitions/envType" }],
"properties": {
"defaultAccess": {
"properties": {
"url": { "pattern": "^((?!-env1).)*$" }
}
}
}
},
"env2Type": { ... },
"env3Type": { ... }
}
}

Is it possible to create a JSON Schema with allOf (multiple if and then) and $ref?

I am trying to create a complex schema that will check for the value of a property and then validate according to the value of that same property. I am wondering if it's possible to use $ref and allOf in the same schema and if so, how? I am having some trouble getting this to work. It may be important to note that I am using AJV. Please see my code below
{
"$ref": "#/definitions/Welcome",
"definitions": {
"Welcome": {
"properties": {
"auth": {
"type": "string",
"enum": ["oauth1","oauth2"]
},
"environment": {
"$ref": "#/definitions/Environment"
}
}
},
"Environment": {
"properties": {
"dev": {
"type": "object"
}
}
},
"Oauth1": {
"type": "object",
"properties": {
"temporary_credentials": {
"type": "string"
}
}
},
"Oauth2": {
"type": "object",
"properties": {
"auth_url": {
"type": "string"
}
}
}
},
"allOf": [
{
"if": {
"auth": {
"const": "oauth1"
}
},
"then": {
"environment": {
"dev": {
"$ref": "#/definitions/Oauth1
}
}
}
},
{
"if": {
"auth": {
"const": "oauth2"
}
},
"then": {
"environment": {
"dev": {
"$ref": "#/definitions/Oauth2
}
}
}
}
]
}
A sample json input to be validated against this schema would be something like this
{
"auth": "oauth1",
"environment": {
"dev": {
"temporary_credentials": "xyzzy"
}
}
}
I feel like there might be an error in my "then" statements or simply the placement of the allOf. The error I would get is something like this "$ref: keywords ignored in schema at path "#"".
In schema version up to and including draft7, once you use "$ref", all other keywords in that level of the schema are ignored. That's what the error is telling you: because you used $ref, other keywords are ignored.
If you only want to use a $ref at the root level, the trick is to wrap it in an "allOf".
But since you already have an allOf at the root level, you can just add the $ref as another branch of the allOf and it will work.
That would look like:
"allOf": [
{
"$ref": "#/definitions/Welcome",
},
{
"if": {
"auth": {
"const": "oauth1"
}
etc.
Note: in the schema you posted, you have two unclosed strings "#/definitions/Oauth1 and "#/definitions/Oauth2. If you had that in your real schema it would be invalid JSON.

JSON Schema `required` allows empty string for value

I'm using a JSON schema template to validate the data that is received by an online form. One of the requirements of the validator is that it allows some questions to be required based on the answers given for other questions.
For example if the question is Do you want a loan? and the user answers yes, then the answer to the question What is the loan to be used for? needs to be set to required so that the user must provide an answer. If the answer is no then the second question is not required.
I'm using definitions to define my questions, and then referencing them below in the main question schema. I read that by using the if-then-else feature provided in draft-07 I could use it to set certain questions to be required based on answers to other questions.
In this particular instance what I would like to happen is that if the user enters the answer Home improvements (General) for question 9, then question 257 will be set to required and MUST be answered, otherwise an error should be thrown.
At the moment, when I enter this validator into https://www.jsonschemavalidator.net/ it does not work as expected. What actually happens is the answer for question 257 can be left blank even if the answer to question 9 is "Home improvements (General)
How can I change my schema to give the behaviour I am trying to get?
JSON Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"question3-9": {
"type": "object",
"properties": {
"answer": {
"type": "string",
"enum": [
"Home improvements (General)",
"Other"
]
}
}
},
"question3-257": {
"type": "object",
"properties": {
"answer": {
"type": "string",
}
}
}
},
"type": "object",
"properties": {
"form_submission": {
"type": "object",
"properties": {
"sections": {
"type": "object",
"properties": {
"3": {
"type": "object",
"properties": {
"questions": {
"type": "object",
"properties": {
"9": {
"$ref": "#/definitions/question3-9"
},
"257": {
"$ref": "#/definitions/question3-257"
}
},
"if": {
"properties": {
"9": {
"properties": {
"answer": {
"enum": [
"Home improvements (General)"
]
}
}
}
}
},
"then": {
"required": [
"257"
]
}
}
}
}
},
"required": [
"3"
]
}
}
}
}
}
JSON to be validated:
{
"form_submission": {
"sections": {
"3": {
"questions": {
"9": {
"answer": "Home improvements (General)",
},
"257": {
"answer": "",
}
}
}
}
}
}
Updated If-Then
"if": {
"properties": {
"9": {
"properties": {
"answer": {
"enum": [
"Home improvements (General)"
]
}
},
"required": ["answer"]
}
},
"required": ["9"]
},
"then": {
"257": {
"properties":{
"answer":{
"minLength": 1
}
}
}
}
Your problem here is you are expecting required to check the value of the key, which it does not.
Required from the current draft-7 specification:
An object instance is valid against this keyword if every item in the
array is the name of a property in the instance.
This means required only checks that the key exists for the object.
It is not related to the value.
For string validation, see the validation key words which are applicable to strings. I suspect you want minLength or pattern (which is regex).
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.3

Metaschema specifying required attribute for all properties

I want to customize a metaschema such that all properties are required to have an additional attribute, for example, how could I require that all properties specify a "type"?
Then this schema should fail:
{
"$schema": "http://json-schema.org/schema#",
"title": "...",
"description": "...",
"type": "object",
"properties": {
"name": {
"description": "..."
}
}
}
But this one should succeed:
{
"$schema": "http://json-schema.org/schema#",
"title": "...",
"description": "...",
"type": "object",
"properties": {
"name": {
"description": "...",
"type": "string"
}
}
}
Unfortunately, writing meta-schemas is not easy. It's being worked on, but there's no good solution yet.
You would have to make a copy of the meta-schema you want to extend and then add "required": ["type"].
But, while we're here, maybe I can convince you not to do this. Making the type keyword required causes problems in some cases. Here are a few examples. https://github.com/json-schema/json-schema/issues/172#issuecomment-124214534
EDIT
After discussing this further, we found that this particular case doesn't have the problems we normally run into with extending meta-schemas because it doesn't need to be recursive. Here is an example of extending the draft-06 schema to include a new keyword called custom which is a boolean and is required only at the top level of a properties schema.
{
"allOf": [
{ "$ref": "http://json-schema.org/draft-06/schema#" },
{
"properties": {
"properties": {
"patternProperties": {
".*": {
"properties": {
"custom": { "type": "boolean" }
},
"required": ["custom"]
}
}
}
}
}
]
}
And here's an example schema that conforms to this meta-schema.
{
"properties": {
"foo": {
"custom": true,
"not": { "type": "string" }
}
}
}
The custom keyword is required for the "foo" schema, but not the not schema or the top level schema.

Why does the "schema" disappear from the "responses" object when importing an OpenAPI definition?

I can successfully import the following OpenAPI definition into Azure API Management.
However, when I export the OpenAPI definition, the "schema" name has been removed from the "responses" object. As a result, developers in my portal are not shown a schema or example for this operation.
My API definition is valid and functions correctly if added to the official editor.
How can I prevent the schema from being stripped out?
{
"swagger": "2.0",
"info": {
"title": "Foo",
"description": "Foo",
"version": "1"
},
"host": "example.org",
"schemes": [
"https"
],
"paths": {
"/foo": {
"get": {
"summary": "List all foo.",
"responses": {
"200": {
"description": "Success.",
"schema": {
"$ref": "#/definitions/Foo"
}
}
}
}
}
},
"definitions": {
"Foo": {
"type": "object",
"properties": {
"example": {
"type": "string",
"description": "An example."
}
}
}
}
}
This problem seems to occur when the definition lacks a "produces" name, in either the root object, or in the operation object.
For example, the following definition should import successfully, and then export without the "schema" being stripped away. Note that the "produces" name has been added to the root object, in between "schemes" and "paths"
{
"swagger": "2.0",
"info": {
"title": "Foo",
"description": "Foo",
"version": "1"
},
"host": "example.org",
"schemes": [
"https"
],
"produces": ["application/json"]
"paths": {
"/foo": {
"get": {
"summary": "List all foo.",
"responses": {
"200": {
"description": "Success.",
"schema": {
"$ref": "#/definitions/Foo"
}
}
}
}
}
},
"definitions": {
"Foo": {
"type": "object",
"properties": {
"example": {
"type": "string",
"description": "An example."
}
}
}
}
}