-
Notifications
You must be signed in to change notification settings - Fork 3
maxLength renders wrong message #6
Comments
Yeah, jjve definitely doesn't support I was hoping to get some movement on acornejo/jjv#25 so I didn't end up rewriting a bunch of jsonschema logic. If you just want nice error messages it might be easier to just switch to something like z-schema. I really need to be able to hook into jjv to do this cleanly, otherwise I'm just recreating a jsonschema validator (which I'm not really interested in doing). |
@whitlockjc Could you provide a working example of your problem? It would be awesome if you set it up in jsfiddle, otherwise I'll settle for links to the offending object and schema (you posted a link to the schema but not the object). If your object doesn't pass because of a maxLength violation, I would expect jjv to tell you that the error was with 'maxLength'. It won't tell you what the expected length was, but that information is already available in the schema, so you are just a lookup away from what you want. However @silas is correct in that the error messages produced for allOf or anyOf might not be very useful. For instance, suppose your object failed on the allOf tests, it means we tried to match your object to a bunch of schemas, and it failed in at least one of them, but possibly many of them. In the later case, which one should we report as an error? The one with the most errors (how do we count them?), the one with the least errors? All of them? |
Below is the full code required to reproduce this. It was identified while working on swagger-tools and to make it as simple as possible to run, I've taken the real world schemas and inlined them in the code so you didn't have to do it yourself. Before I give you the code, let me show you the expected output and actual output. Expected Output
Actual Output
And here is the code: 'use strict';
var jjv = require('jjv');
var jjve = require('jjve');
var validator = jjv();
var dataTypeBaseJson = {
"id": "dataTypeBase.json",
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Data type fields (section 4.3.3)",
"type": "object",
"oneOf": [
{
"required": [
"type"
]
},
{
"required": [
"$ref"
]
}
],
"properties": {
"type": {
"type": "string"
},
"$ref": {
"type": "string"
},
"format": {
"type": "string"
},
"defaultValue": {
"not": {
"type": [
"array",
"object",
"null"
]
}
},
"enum": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true,
"minItems": 1
},
"minimum": {
"type": "string"
},
"maximum": {
"type": "string"
},
"items": {
"$ref": "#/definitions/itemsObject"
},
"uniqueItems": {
"type": "boolean"
}
},
"dependencies": {
"format": {
"oneOf": [
{
"properties": {
"type": {
"enum": [
"integer"
]
},
"format": {
"enum": [
"int32",
"int64"
]
}
}
},
{
"properties": {
"type": {
"enum": [
"number"
]
},
"format": {
"enum": [
"float",
"double"
]
}
}
},
{
"properties": {
"type": {
"enum": [
"string"
]
},
"format": {
"enum": [
"byte",
"date",
"date-time"
]
}
}
}
]
}
},
"definitions": {
"itemsObject": {
"oneOf": [
{
"type": "object",
"required": [
"$ref"
],
"properties": {
"$ref": {
"type": "string"
}
},
"additionalProperties": false
},
{
"allOf": [
{
"$ref": "#"
},
{
"required": [
"type"
],
"properties": {
"type": {},
"format": {}
},
"additionalProperties": false
}
]
}
]
}
}
};
var modelsObjectJson = {
"id": "modelsObject.json",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": [
"id",
"properties"
],
"properties": {
"id": {
"type": "string"
},
"description": {
"type": "string"
},
"properties": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/propertyObject"
}
},
"subTypes": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
},
"discriminator": {
"type": "string"
}
},
"dependencies": {
"subTypes": [
"discriminator"
]
},
"definitions": {
"propertyObject": {
"allOf": [
{
"not": {
"$ref": "#"
}
},
{
"$ref": "dataTypeBase.json#"
}
]
}
}
};
var oauth2GrantTypeJson = {
"id": "oauth2GrantType.json",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"minProperties": 1,
"properties": {
"implicit": {
"$ref": "#/definitions/implicit"
},
"authorization_code": {
"$ref": "#/definitions/authorizationCode"
}
},
"definitions": {
"implicit": {
"type": "object",
"required": [
"loginEndpoint"
],
"properties": {
"loginEndpoint": {
"$ref": "#/definitions/loginEndpoint"
},
"tokenName": {
"type": "string"
}
},
"additionalProperties": false
},
"authorizationCode": {
"type": "object",
"required": [
"tokenEndpoint",
"tokenRequestEndpoint"
],
"properties": {
"tokenEndpoint": {
"$ref": "#/definitions/tokenEndpoint"
},
"tokenRequestEndpoint": {
"$ref": "#/definitions/tokenRequestEndpoint"
}
},
"additionalProperties": false
},
"loginEndpoint": {
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"format": "uri"
}
},
"additionalProperties": false
},
"tokenEndpoint": {
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"format": "uri"
},
"tokenName": {
"type": "string"
}
},
"additionalProperties": false
},
"tokenRequestEndpoint": {
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"format": "uri"
},
"clientIdName": {
"type": "string"
},
"clientSecretName": {
"type": "string"
}
},
"additionalProperties": false
}
}
};
var authorizationObjectJson = {
"id": "authorizationObject.json",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"additionalProperties": {
"oneOf": [
{
"$ref": "#/definitions/basicAuth"
},
{
"$ref": "#/definitions/apiKey"
},
{
"$ref": "#/definitions/oauth2"
}
]
},
"definitions": {
"basicAuth": {
"required": [
"type"
],
"properties": {
"type": {
"enum": [
"basicAuth"
]
}
},
"additionalProperties": false
},
"apiKey": {
"required": [
"type",
"passAs",
"keyname"
],
"properties": {
"type": {
"enum": [
"apiKey"
]
},
"passAs": {
"enum": [
"header",
"query"
]
},
"keyname": {
"type": "string"
}
},
"additionalProperties": false
},
"oauth2": {
"type": "object",
"required": [
"type",
"grantTypes"
],
"properties": {
"type": {
"enum": [
"oauth2"
]
},
"scopes": {
"type": "array",
"items": {
"$ref": "#/definitions/oauth2Scope"
}
},
"grantTypes": {
"$ref": "oauth2GrantType.json#"
}
},
"additionalProperties": false
},
"oauth2Scope": {
"type": "object",
"required": [
"scope"
],
"properties": {
"scope": {
"type": "string"
},
"description": {
"type": "string"
}
},
"additionalProperties": false
}
}
};
var parameterObjectJson = {
"id": "parameterObject.json",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"allOf": [
{
"$ref": "dataTypeBase.json#"
},
{
"required": [
"paramType",
"name"
],
"properties": {
"paramType": {
"enum": [
"path",
"query",
"body",
"header",
"form"
]
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"required": {
"type": "boolean"
},
"allowMultiple": {
"type": "boolean"
}
}
},
{
"description": "type File requires special paramType and consumes",
"oneOf": [
{
"properties": {
"type": {
"not": {
"enum": [
"File"
]
}
}
}
},
{
"properties": {
"type": {
"enum": [
"File"
]
},
"paramType": {
"enum": [
"form"
]
},
"consumes": {
"enum": [
"multipart/form-data"
]
}
}
}
]
}
]
};
var operationObjectJson = {
"id": "operationObject.json",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"allOf": [
{
"$ref": "dataTypeBase.json#"
},
{
"required": [
"method",
"nickname",
"parameters"
],
"properties": {
"method": {
"enum": [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
]
},
"summary": {
"type": "string",
"maxLength": 120
},
"notes": {
"type": "string"
},
"nickname": {
"type": "string",
"pattern": "^[a-zA-Z0-9_]+$"
},
"authorizations": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"$ref": "authorizationObject.json#/definitions/oauth2Scope"
}
}
},
"parameters": {
"type": "array",
"items": {
"$ref": "parameterObject.json#"
}
},
"responseMessages": {
"type": "array",
"items": {
"$ref": "#/definitions/responseMessageObject"
}
},
"produces": {
"$ref": "#/definitions/mimeTypeArray"
},
"consumes": {
"$ref": "#/definitions/mimeTypeArray"
},
"deprecated": {
"enum": [
"true",
"false"
]
}
}
}
],
"definitions": {
"responseMessageObject": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"$ref": "#/definitions/rfc2616section10"
},
"message": {
"type": "string"
},
"responseModel": {
"type": "string"
}
}
},
"rfc2616section10": {
"type": "integer",
"minimum": 100,
"maximum": 600,
"exclusiveMaximum": true
},
"mimeTypeArray": {
"type": "array",
"items": {
"type": "string",
"format": "mime-type"
}
}
}
}
var apiDeclarationJson = {
"id": "apiDeclaration.json",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": [
"swaggerVersion",
"basePath",
"apis"
],
"properties": {
"swaggerVersion": {
"enum": [
"1.2"
]
},
"apiVersion": {
"type": "string"
},
"basePath": {
"type": "string",
"format": "uri",
"pattern": "^https?://"
},
"resourcePath": {
"type": "string",
"format": "uri",
"pattern": "^/"
},
"apis": {
"type": "array",
"items": {
"$ref": "#/definitions/apiObject"
}
},
"models": {
"type": "object",
"additionalProperties": {
"$ref": "modelsObject.json#"
}
},
"produces": {
"$ref": "#/definitions/mimeTypeArray"
},
"consumes": {
"$ref": "#/definitions/mimeTypeArray"
},
"authorizations": {
"$ref": "authorizationObject.json#"
}
},
"additionalProperties": false,
"definitions": {
"apiObject": {
"type": "object",
"required": [
"path",
"operations"
],
"properties": {
"path": {
"type": "string",
"format": "uri-template",
"pattern": "^/"
},
"description": {
"type": "string"
},
"operations": {
"type": "array",
"items": {
"$ref": "operationObject.json#"
}
}
},
"additionalProperties": false
},
"mimeTypeArray": {
"type": "array",
"items": {
"type": "string",
"format": "mime-type"
}
}
}
};
var data = {
"apiVersion": "1.0.0",
"apis": [
{
"operations": [
{
"authorizations": {},
"method": "GET",
"nickname": "getAllPets",
"summary": "Find all Pets",
"parameters": [],
"type": "array",
"items": {
"$ref": "Pet"
}
}
],
"path": "/pets"
}
],
"basePath": "http://localhost/api",
"resourcePath": "/pets",
"swaggerVersion": "1.2"
}
var result;
validator.addSchema('dataTypeBaseJson.json', dataTypeBaseJson);
validator.addSchema('modelsObjectJson.json', modelsObjectJson);
validator.addSchema('oauth2GrantTypeJson.json', oauth2GrantTypeJson);
validator.addSchema('authorizationObjectJson.json', authorizationObjectJson);
validator.addSchema('parameterObjectJson.json', parameterObjectJson);
validator.addSchema('operationObjectJson.json', operationObjectJson);
validator.addSchema('apiDeclarationJson.json', apiDeclarationJson);
validator.addFormat('uri', function() {
return true;
});
data.apis[0].operations[0].summary = new Array(122).join('*');
result = validator.validate(apiDeclarationJson, data);
console.log(jjve(validator)(apiDeclarationJson, data, result)); |
Just to be clear this definitely isn't a problem with jjv, this is purely are result of how jjve is implemented. I basically ended up re-creating a bit of jjv inside jjve in a hacky way in order to get more user friendly errors messages. In at attempt to stop re-impelementing a bunch of jjv I created that other pull request which should give me direct access to data as it's validated and get rid of weirdness like the above. Sorry for the confusion, I didn't mean to suggest jjv was broken, I just mean't I want to fix this and other issues using the result of the originally linked pull request. |
If it matters, I didn't take it that way. |
I'm validating a Swagger 1.2 operation. The schema for the operation object specifies that
summary
has amaxLength
of120
(operationObject.json#L11) and whenever that constraint is violated, the error message hasundefined
for themaxLength
value and it ends up with a message like:String is too long (215 chars), maximum undefined
.The text was updated successfully, but these errors were encountered: