Here's my JSON Schema:
{
"required": [
"username",
"password",
"confirmPassword"
],
"properties": {
"username": {
"minLength": 3,
"type": "string"
},
"password": {
"minLength": 6,
"type": "string"
},
"confirmPassword": {
"const": {
"$data": "1/password"
},
"type": "string"
}
},
"type": "object"
}
Here's my data:
{
"username": "abc",
"password": "asdfasdf",
"confirmPassword": "asdfasdf"
}
You can copy-paste those into this online validator to see what happens.
The confirmPassword field is failing validation with error message:
Value "asdfasdf" does not match const.
I believe there is a problem with my relative JSON pointer but I can't figure out what the correct syntax is.
AFAICT, 1/password means "go up one level, and then check the password property" but that doesn't appear to be the case. What's correct syntax?
The specific implementation I'm using is AJV which says it does support relative-JSON-pointers.
Turns out the only problem was that I forgot to set the $data option to true. e.g.
const ajv = new Ajv({
allErrors: true,
$data: true,
});
Related
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Text",
"description": "Form Text ",
"type": "object",
"properties": {
"value": {
"type": "string",
"default": "",
"minLength":"this needs to point to fieldSpecific.minLength of the validating object"
}
}
can we do something like this the object we receive to validate will be as below
{
"fieldSpecific": {
"minLength": 4
},
"value": "asfasfasfafasfasF"
}
in the above-received object we receive minLength under fieldSpecific can we write a JSON schema to refer minLength in field specific to validate the minLength of the value?
JSON Schema doesn't support this out of the box, but you can do it with JsonSchema.Net and the extension Data Vocabulary package.
The docs can be found on json-everything.net.
Here's what your schema would look like with this:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Text",
"description": "Form Text ",
"type": "object",
"properties": {
"value": {
"type": "string",
"default": "",
"data": {
"minLength": "/fieldSpecific/minLength"
}
}
}
Disclaimer: these libraries are mine.
In my Chai-Test (using it for PostMan) I want to validate my API-response-design. For that I have written a Chai-Test:
pm.test("Check response schema", () => {
const schema = {
"type": "object",
"properties": {
"success": { "type": "boolean" },
"data": { "type": "object" },
"err": { "type": "object" },
"info": { "type": "string" }
},
"required": ["success", "data", "err", "info"]
}
pm.response.to.have.jsonSchema(schema)
})
My problem now is, that either the data or the err object is defined based on whether the request to the API was successful or not. I wanted to accomplish that by using two types for the data and the err: object AND null. So, how can I check for two types with the jsonSchema? Or is there an other and better way to do this?
You can do that:
"data": { "type": ["object", "null"] },
"err": { "type": ["object", "null"] }
Yup contain a method name validationError whose one of properties is "inner". Accordingly with the documentation:
in the case of aggregate errors, inner is an array of ValidationErrors
throw earlier in the validation chain. When the abortEarly option is
false this is where you can inspect each error thrown, alternatively,
errors will have all of the messages from each inner error.
However, it's properly working is not quite clear to me. How exactly I do to access this property and use it in my code.
Here, I'm trying to use in this application but it seems not working.
function validator (req, res, next) {
yup.setLocale({
mixed: {
default: 'Não é válido',
}
});
const schema = yup.object().shape({
name: yup.string().required("Legendary name is required"),
type: yup.string().required("Legendary type is required"),
description: yup.string().required("Legendary description is required").min(10)
});
let messageError = new yup.ValidationError([`${req.body.name}`, `${req.body.type}`, `${req.body.description}`]);
if(!schema.isValidSync(req.body, {abortEarly: false})) {
return res.status(400).json(messageError.inner);
}
When I run it with insomnia, I get a empty array only.
Can someone help me with this, please ?
ValidationError is thrown is by the validate* methods (validate, validateSync, validateAt, and validateSyncAt) when the validation fails. isValidSync returns a boolean and doesn't throw any errors. Use validateSync and add a catch block to access the validation errors.
messageError.inner returns an empty array since messageError is a standalone ValidationError object which isn't associated with the schema in any way.
try {
schema.validateSync(req.body, { abortEarly: false })
} catch (err) {
// err is of type ValidationError
return res.status(400).json(err.inner)
}
curl -s -X POST http://localhost:5000/test | jq
[
{
"name": "ValidationError",
"path": "name",
"type": "required",
"errors": [
"Legendary name is required"
],
"inner": [],
"message": "Legendary name is required",
"params": {
"path": "name"
}
},
{
"name": "ValidationError",
"path": "type",
"type": "required",
"errors": [
"Legendary type is required"
],
"inner": [],
"message": "Legendary type is required",
"params": {
"path": "type"
}
},
{
"name": "ValidationError",
"path": "description",
"type": "required",
"errors": [
"Legendary description is required"
],
"inner": [],
"message": "Legendary description is required",
"params": {
"path": "description"
}
}
]
Im using Ajv version 07.
I am trying to validate that the value of a property, returned by the JSON response body is of type and format double in postman, using ajv validation, however, I'm not being able to do it. I've tried searching it online, but still did not find anything about it.
I've tried typing the following:
"type" : "double",
"format": "double"
"type": "Double",
"format": "Double"
"type":"number"
"format":"double"
All the above attempts were unsuccessful as they all come with an error message saying either:
Error: unknown type "double" is used in schema
or
Error: unknown format "double" is used in schema
Would anyone be able to help me with this please?
schema
var Ajv = require ('ajv'),
ajv = new Ajv ({logger:console}),
expectedResponseSchema =
{
"items": {
"required": [
"payments"
],
"properties": {
"payments": {
"items": {
"required": [
"amount"
]
"properties": {
"amount": {
"$id": "#/items/properties/payments/items/properties/amount",
"type": "number",
"format": "double"
}
}
}
}
}
}
Postman test
var currentSchPmExpTest;
try{
currentSchPmExpTest = ' expectedResponseSchema variable';
pm.expect(ajv.validate(expectedResponseSchema, jsonData)).to.be.true;
pm.test('Test 1 - PASSED - expectedResponseSchema variable data matches schema returned by body response!', () => true);
} catch(e){
pm.test('Test 1 - FAILED - Expected data does not match response body data!', () => {throw new Error(e.message + " in " + currentSchPmExpTest)});
}
body response
[
{
"payments": [
{
"amount": 2.200000045367898,
}
]
}
]
I'm not sure where you're getting the type and format from but as per the AJV docs (could be out of date) that isn't a valid type.
EDIT:
From your update, I would recommend changing the test script to something like this so that you correct part of the schema is getting checked:
let schema = {
"type": "array",
"items": {
"type": "object",
"required": [
"payments"
],
"properties": {
"payments": {
"type": "array",
"items": {
"type": "object",
"required": [
"amount"
],
"properties": {
"amount": {
"type": "number",
}
}
}
}
}
}
}
pm.test("Check Schema", () => {
pm.response.to.have.jsonSchema(schema)
})
The try/catch block can be added around this if you need too.
I'm using the loopback framework to create a RESTful API for my application.
Following the documentation, I create my own Customer Model extending the built-in model User.
What I'm trying to achieve is:
How can I rename and remove some properties from this built-in model?
{
"name": "Cliente",
"plural": "Clientes",
"base": "User",
"idInjection": false,
"strict":"true",
...
}
{
"name": "User",
"properties": {
"realm": {
"type": "string"
},
"username": {
"type": "string"
},
"password": {
"type": "string",
"required": true
},
"email": {
"type": "string",
"required": true
},
"emailVerified": "boolean",
"verificationToken": "string"
},
...
}
I reached the results modyfing the loopbacks models inside the node modules, but this solution does not seem the right way, is there a way to config this in my code instead change loopback base models?
I think what you are trying to do is "rename" a property, am I correct?
If so, you can do the following:
"senha": {
"type": "string",
"id": true,
"required": true,
"index": true,
"postgresql": {
"columnName": "password"
}
}
Notice that I have a "postgresql" attribute, which depends on your database connector. Check it here. Inside that attribute I have a "columnName", which is the real name of that column in my database. So "senha" is the new name of that attribute.
For hiding the username property, you could do the following in the root object:
"hidden":["username"]
Your final file should look something like this:
{
"name": "Cliente",
"plural": "Clientes",
"base": "User",
"idInjection": false,
"strict": "true",
"properties": {
"realm": {
"type": "string"
},
"username": {
"type": "string"
},
"senha": {
"type": "string",
"required": true,
"postgresql": {
"columnName": "password"
}
},
"email": {
"type": "string",
"required": true
},
"emailVerified": "boolean",
"verificationToken": "string"
},
"hidden": ["username"]
}