ValidationError when posting JSON - javascript

I have this schema for authors:
module.exports = {
"id": "Author",
"properties": {
"name": {
"type": "string",
"description": "The full name of the author"
},
"description": {
"type": "string",
"description": "A small bio of the author"
},
"books": {
"type": "array",
"description": "The list of books published on at least one of the stores by this author",
"items": {
"$ref": "Book"
}
},
"website": {
"type": "string",
"description": "The website url of the author"
},
"avatar": {
"type": "string",
"description": "The url of the avatar of this author"
}
}
}
When I POST to http://localhost:9000/authors/ to create a new author I get this error:
error: Error of type InternalServerError found: ValidationError: books: Cast to Array failed for value "[ 'The Twits', 'The BFG' ]" at path "books"
This is the JSON I'm posting
{
"name": "Roald Dahl",
"description": "Writes childrens novels",
"books": [
"The Twits",
"The BFG"
],
"website": "www.roalddahl.com",
"avatar": "https://www.natgeokids.com/wp-content/uploads/2016/11/Roald-Dahl-1-1.jpg"
}
To the best of my knowledge this JSON is correct. The error seems to suggest there is an issue with the books array. Is this the case and if so, how do I fix it?
Adding Book schema:
module.exports = {
"id": "Book",
"properties": {
"title": {
"type": "string",
"descrtiption": "The title of the book"
},
"authors": {
"type": "array",
"description": "List of authors of the book",
"items": {
"$ref": "Author"
}
},
"isbn_code": {
"type": "string",
"description": "The stores where clients can buy this book"
},
"stores": {
"type": "array",
"description": "The stores where clients can buy this book",
"items": {
"type": "object",
"properties": {
"store": {
"$ref": "Store"
},
"copies": {
"type": "integer"
}
}
}
},
"genre": {
"type": "string",
"description": "Genre of the book",
},
"description": {
"type": "string",
"description": "Description of the book"
},
"reviews": {
"type": "array",
"items": {
"$ref": "ClientReview"
}
},
"price": {
"type": "number",
"minimum": 0,
"description": "The price of this book"
}
}
}

You are posting JSON with the books field as an array of strings, so your validator object should specify:
items: { type: "string" },

Related

Angular Schema Form - Require Field if Integer Field is Not Null

I am trying to create a form using the Angular JSON Schema Form. I want one field (dropdown1) to be required when another field (number1) is populated. I am able to get the following form + schema working in the SchemaForm.io Sandbox, but when I put it into my site, the dropdown field is missing.
Here is my schema:
{
"type": "object",
"properties": {
"isChecked": {
"title": "checked?",
"type": "boolean"
},
"text1": {
"title": "text1",
"type": "number",
"minimum": 0,
"maximum": 100,
"condition": "model.isChecked"
},
"number1": {
"title": "number1",
"type": "number",
"minimum": 0,
"condition": "model.isChecked"
},
"dropdown1": {
"title": "",
"type": "string",
"enum": ["Days", "Months", "Years"],
"condition": "model.isChecked"
},
"comment": {"type": "string", "Title": "Comment"}
}
}
Here is my form:
[
"isChecked",
{
"key": "text1",
"type": "decimal",
"validationMessages": {
"maximum": "text1 must be 100 or lower.",
"minimum": "text1 must be 0 or higher.",
"required": "This field is required"
},
"required": false
},
{
"key": "number1",
"type": "number",
"validationMessages": {
"minimum": "number1 must be 0 or higher."
},
"required": false
},
{
"key": "dropdown1",
"required": false,
"condition": "model.number1 === null"
},
{
"key": "dropdown1",
"required": true,
"condition": "model.number1 > 0",
"validationMessages": {
"required": "dropdown1 is required."
}
},
{
"key": "comment",
"type": "textarea"
}
]
You can use the "dependencies" property (https://json-schema.org/understanding-json-schema/reference/object.html#property-dependencies). The example requires billing_address to be present when a credit_card is provided:
{
"type": "object",
"properties": {
"credit_card": {
"type": "number"
},
"billing_address": {
"type": "string"
}
},
"dependencies": {
"credit_card": [
"billing_address"
]
}
}
This implementation supports "dependencies":
https://github.com/dashjoin/json-schema-form
You can check out the online example here:
https://dashjoin.github.io/#/example/dependencies
Here is the solution I found:
"condition": {
"functionBody": "return model.number1 === undefined && model.isChecked"
}

Form multiple groups for a complex object in uiSchema

Description
I'm using library react-json-schema to display JSON schema as a form.
I have a requirement, where the form is very large, hence I'm using uiSchema groups to form the tabs. But one of my attributes, which is an object, contains many objects. I want to spread these child objects further into the tabs.
I used the code suggested in #784 . I went through GroupedSchema code and it checks only in properties of schema, if the given field is present or not. It doesn't go deep down inside a nested object.
Steps to Reproduce
1.A dummy Schema:
{
"A": {
"type": "string",
"title": "A"
},
"B": {
"type": "string",
"title": "B"
},
"C": {
"type": "string",
"title": "C"
},
"D": {
"type": "object",
"properties": {
"DA": {
"type": "object",
"properties": {
"DAA": {
"type": "string",
"title": "DAA"
},
"DAB": {
"type": "string",
"title": "DAB"
}
}
},
"DB": {
"type": "object",
"properties": {
"DBA": {
"type": "string",
"title": "DBA"
},
"DBB": {
"type": "string",
"title": "DBB"
}
}
},
"DC": {
"type": "object",
"properties": {
"DCA": {
"type": "string",
"title": "DCA"
},
"DCB": {
"type": "string",
"title": "DCB"
}
}
}
}
}
}
Expected behavior
I'm trying to get tabs for A,B,C,DA,DB,DC
Here is the link to codesandbox

Post request with array

I want to test my Web API with a postman on the javascript app.
I have the following swagger.
"/attachment/erase": {
"post": {
"summary": "Erase ",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "folder",
"in": "query",
"type": "string",
"description": "folder('s) detail",
"required": true
},
{
"name": "type",
"in": "query",
"type": "string",
"description": "ABC or BCD",
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"type": "object",
"required": ["files"],
"properties": {
"attachments": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"description": "The file(s) to delete"
}
],
"responses": {
"200": {
"description": "file(s) erased."
}
}
}
}
So I send the following request :
with the following body :
In return, I get an error 415.
What I am doing wrong?
You're sending x-www-form-urlencoded when the API is expecting application/json.
How about passing a form-data parameter file, please refer the image

Validate an API response against JSON schema using AJV

I have many days reading a lot and doing several tests with this, without the expected results.
I need validate an API response with its JSON schema (Swagger 2.0). The JSON is longer but I've reduced it to simply. I need to know if "code" and "message" keywords in the response have the type and values defined. Here the code I'm using:
var Ajv = require('ajv');
var ajv = new Ajv();
var schema = {
"host": "cert",
"paths": {
"products": {
"get": {
"responses": {
"401": {
"description": "Problem with the client request",
"headers": {
"x-correlator": {
"type": "string",
"format": "uuid",
"description": "Correlation id"
}
},
"schema": {
"$ref": "file:///../errors.json#/definitions/Unauthenticated"
}
}
}
}
},
"products": {
"get": {
"responses": {
"401": {
"description": "Problem with the client request",
"headers": {
"x-correlator": {
"type": "string",
"format": "uuid",
"description": "Correlation id"
}
},
"schema": {
"$ref": "file:///../errors.json#/definitions/Unauthenticated"
},
"examples": {
"application/json": {
"code": "UNAUTHENTICATED",
"message": "Authentication error"
}
}
}
}
}
}
}
}
var errors_schema = {
"info": {
"description": "Common errors",
"version": "3.0.1",
"title": "Common errors",
"contact": {
"name": "Team"
}
},
"definitions": {
"ModelError": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string",
"description": "A human readable description"
}
}
},
"Unauthenticated": {
"allOf": [
{
"type": "object",
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"enum": [
"UNAUTHENTICATED"
],
"default": "UNAUTHENTICATED",
"description": "Request not authenticated due to missing, invalid, or expired credentials."
}
}
},
{
"$ref": "#/definitions/ModelError"
}
]
}
}
}
ajv.addSchema(errors_schema, 'file:///../errors.json');
var testajv = ajv.compile(schema);
var response = {"code": 123, "message":"token expired"}
var valid = testajv(response);
console.log(valid);
if(!valid) {
console.log(testajv.errors);
}
As you see the keyword "code" in the response is '123' integer but in the schema it is defined as string. Independently of the value the validation always gets 'true'. What should I do to get my needs? Thanks in advance.
Swagger schema contains multiple JSON schemas organized in API structure, you need to address a correct part of Swagger schema to employ JSON schema for validation.
Please check example code (https://runkit.com/embed/bwj42juwyjo4):
var Ajv = require('ajv');
var ajv = new Ajv();
var schema = {
"host": "cert",
"paths": {
"products": {
"get": {
"responses": {
"401": {
"description": "Problem with the client request",
"headers": {
"x-correlator": {
"type": "string",
"format": "uuid",
"description": "Correlation id"
}
},
"schema": {
"$ref": "errors.json#/definitions/Unauthenticated"
}
}
}
}
},
"products": {
"get": {
"responses": {
"401": {
"description": "Problem with the client request",
"headers": {
"x-correlator": {
"type": "string",
"format": "uuid",
"description": "Correlation id"
}
},
"schema": {
"$ref": "errors.json#/definitions/Unauthenticated"
},
"examples": {
"application/json": {
"code": "UNAUTHENTICATED",
"message": "Authentication error"
}
}
}
}
}
}
}
}
var errors_schema = {
"info": {
"description": "Common errors",
"version": "3.0.1",
"title": "Common errors",
"contact": {
"name": "Team"
}
},
"definitions": {
"ModelError": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string",
"description": "A human readable description"
}
}
},
"Unauthenticated": {
"allOf": [
{
"type": "object",
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"enum": [
"UNAUTHENTICATED"
],
"default": "UNAUTHENTICATED",
"description": "Request not authenticated due to missing, invalid, or expired credentials."
}
}
},
{
"$ref": "#/definitions/ModelError"
}
]
}
}
}
ajv.addSchema(errors_schema, 'errors.json');
ajv.addSchema(schema, 'swagger.json')
var testajv = ajv.compile({ $ref: 'errors.json#/definitions/Unauthenticated' });
console.log(testajv({"code": 123, "message":"token expired"}), testajv.errors); // Fails
console.log(testajv({"code": "AAA", "message":"token expired"}), testajv.errors); // Fails
console.log(testajv({"code": "UNAUTHENTICATED", "message":"token expired"}), testajv.errors); // Passes
var testajv2 = ajv.compile({ $ref: 'swagger.json#/paths/products/get/responses/401/schema' });
console.log(testajv2({"code": 123, "message":"token expired"}), testajv2.errors); // Fails
console.log(testajv2({"code": "AAA", "message":"token expired"}), testajv2.errors); // Fails
console.log(testajv2({"code": "UNAUTHENTICATED", "message":"token expired"}), testajv2.errors); // Passes
Some more information in relevant ajv issue: https://github.com/epoberezkin/ajv/issues/195
Use type as number instead of string in code property.
"properties": {
"code": {
"type": "number",
"enum": [
"UNAUTHENTICATED"
],
"default": "UNAUTHENTICATED",
"description": "Request not authenticated due to missing, invalid, or expired credentials."
}
}

Passing function argument to retrieve data from an object

I am have some trouble with a script I am working on. I have been provided with an object with multiple items from a product catalog.
What I am trying to do is to write a function which to which will allow me to render this data easily.
<script type="application/javascript">
SKUinfo =
{
"s238554": {
"Age": {
"Description": "Age 18+",
"Thumbnail": "/productImages/assets/img/icon18.gif"
},
"Barcode": {
"Barcode": "50622132430794"
},
"Currency": "£",
"Description": "Description goes here",
"Id": 44305,
"Packshots": [
"/productImages/238556/1min.jpg",
"/productImages/238556/2med.jpg",
"/productImages/238556/3max.jpg"
],
"Pegis": [],
"Platform": {
"Button": "Xbox 360",
"ID": 0
},
"Publisher": {
"Description": null
},
"Release": "/Date(1392940800000+0000)/",
"Screenshots": [
{
"ScreenshotMax": "/productImages/238556/5scrmax1.jpg",
"ScreenshotMin": "/productImages/238556/4scrmin1.jpg"
}
],
"Title": "Product title 2 goes here",
"Variants": [
{
"Id": 58242,
"MaxOrderQuantity": 3,
"Presellable": true,
"Price": 29.97,
"PriceCultureFormat": "29.97",
"PriceWithCurrencyFormat": "£29.97",
"Sku": 238556,
"Type": {
"Description": "New"
}
},
],
"Vendor": {
"Description": ""
},
},
"s238556": {
"Age": {
"Description": "Age 18+",
"Thumbnail": "/productImages/assets/img/pegi/icon18.gif"
},
"Barcode": {
"Barcode": "5060134530794"
},
"Currency": "£",
"Description": "Description here",
"Id": 654654,
"Packshots": [
"/productImages/238556/1min.jpg",
"/productImages/238556/2med.jpg",
"/productImages/238556/3max.jpg"
],
"Pegis": [],
"Platform": {
"Button": "PlayStation 3",
"ID": 0
},
"Publisher": {
"Description": null
},
"Release": "/Date(1392940800000+0000)/",
"Screenshots": [
{
"ScreenshotMax": "/productImages/238556/5scrmax1.jpg",
"ScreenshotMin": "/productImages/238556/4scrmin1.jpg"
},
{
"ScreenshotMax": "/productImages/238556/7scrmax2.jpg",
"ScreenshotMin": "/productImages/238556/6scrmin2.jpg"
},
],
"Title": "Product title 2 goes here",
"Variants": [
{
"Id": 58242,
"MaxOrderQuantity": 3,
"Presellable": true,
"Price": 29.97,
"PriceCultureFormat": "29.97",
"PriceWithCurrencyFormat": "£29.97",
"Sku": 238556,
"Type": {
"Description": "New"
}
},
],
"Vendor": {
"Description": ""
},
"VideoHTML": "html here",
"status": {
"Response": "product found",
"Success": true
}
}
}
</script>
The above example is the output I get for two products.
If I try to get access to this data this is where I have a problem
<script type="application/javascript">
function getSKU(s)
{
console.log(SKUinfo.s.Title);
}
getSKU(s238554);
</script>
I imagine this is being caused when I am passing the argument s back to the function getSKU a the node selection in the data object. In this I would expect the console output to be the Title from SKU s238554.
What I get however, is: Uncaught ReferenceError: s238554 is not defined
I would appreciate any guidance that can be offered as I am a javascript novice.
Access your property by used[] on SKUinfo.s.Title like SKUinfo[s].Title
And also pass your property name within the quotes 's238554' as it's not variable.
Something like this.
function getSKU(s){
console.log(SKUinfo[s].Title);
}
getSKU('s238554'); // s238554 within quotes.

Categories

Resources