What is the purpose of "additionalItems" property on arrays in rjsf? - javascript

I'm studying rjsf documentation and I'm confused about the additionalItems section of array docs.
Here is the example code from the docs:
const Form = JSONSchemaForm.default;
const schema = {
type: "array",
items: {
type: "string"
},
additionalItems: {
type: "boolean"
}
};
ReactDOM.render((
<Form schema={schema} />
), document.getElementById("app"));
and here is the official codepen
The rendered form seems to behave exactly the same if I remove the additionalItems, so what is the purpose? I guess it has one, since it's explicitly brought up in the docs, but I can't figure it out :)

additionalItems: <schema> is used to indicate how items are treated beyond the enumerated items you specify in the schema, or even if they are allowed at all.
In this schema, the first array item must be a string, the second must be a number, but any additional items beyond that are allowed and can be anything:
{
"type": "array",
"items": [
{ "type": "string" },
{ "type": "number" }
]
}
In this schema, the first item must be a string, the second must be a number, and all items after that must be booleans:
{
"type": "array",
"items": [
{ "type": "string" },
{ "type": "number" }
],
"additionalItems": { "type": "boolean" }
}
And in this schema, there are no more items permitted at all after the first two:
{
"type": "array",
"items": [
{ "type": "string" },
{ "type": "number" }
],
"additionalItems": false
}
You can read more about this keyword in the documentation: https://json-schema.org/understanding-json-schema/reference/array.html

Related

Is there a way to search for keywords across multiple collections in MongoDB?

MongoDB Atlas Cluster version: 5.0.12
MERN Stack Application
Simple Search App that returns Specific ads when keywords are typed in an input.
Front end is handled by React-Redux.
And I am using Axios to request my server for data.
Server is using Mongo's aggregate pipeline function to search for text using $search,
and then a few different operators to fetch data from another collection.
There are two collections, the main one has a foreign key that references the second one.
Here is a sample json of both the collections
ads: {
_id: 1,
companyId: 1,
primaryText: "",
description: "",
CTA: "Sign Up",
imageUrl: "",
heading: "",
}
companies: {
_id: 1,
name: "Levi's",
url: "",
}
This is the search index that I have been using to look for keywords in the collection.
{
"mappings": {
"dynamic": true,
"fields": {
"company": {
"fields": {
"name": [
{
"dynamic": true,
"type": "document"
},
{
"type": "string"
}
]
},
"type": "document"
},
"description": [
{
"dynamic": true,
"type": "document"
},
{
"type": "string"
}
],
"heading": [
{
"dynamic": true,
"type": "document"
},
{
"type": "string"
}
],
"primaryText": [
{
"dynamic": true,
"type": "document"
},
{
"type": "string"
}
]
}
}
}
Mongo doesn't let me query $search anywhere in the pipeline except as the first operation.
So the order that works is this
$seach --> $lookup --> $project --> $unwind
This works but the only problem is that when I try to search for keyword that is present in the companies collection, like name: "Levi's", it doesn't respond with the corresponding ad.
So, In short I am trying to find a way to apply $search on a collection that has the gone through a $lookup.
Thank you, and I appreciate you spending time reading this.

ChaiJS jsonSchema check for multiple types

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"] }

JSON Schema "oneOf" each?

Is it possible to make a JSON Schema which validates that an array contains at least 1 instance of three non-overlapping types. A simple example is an array of numbers of any length that contains at least one 1, one 2, and one 3.
I can't use allOf because that will validate that every number in the array is a 1, 2, and 3 - which no number can be 😅
I can't use anyOf because then I can have an array with only one element 😢
I can't use oneOf because, again, I can have an array with one number
(...also I'm unclear if I should be working with the contains key or inside the items key)
What I'm looking for is a way to say "one of each" of these items. Is it possible with JSON Schema?
Here's a broken example with oneOf
{
"type": "object",
"properties": {
"numbers": {
"type": "array",
"contains": {
"oneOf": [
{
"const": 1
},
{
"const": 2
},
{
"const": 3
}
]
},
"items": {
"type": "number"
}
}
}
}
[1] – Should NOT validate
[1,2] - Should NOT validate
[1,2,3] - SHOULD validate
[1,2,3,4] - SHOULD validate
You can put the contains inside of an allOf:
{
"type": "object",
"properties": {
"numbers": {
"type": "array",
"allOf": [
{
"contains": {
"const": 1
}
},
{
"contains": {
"const": 2
}
},
{
"contains": {
"const": 3
}
}
]
}
}
}``

How to verify if a value is of format and/or type double using ajv schema validation?

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.

Nested forEach issue

I have two arrays of object, the first array (printers, around 80 elements) is made of the following type of objects:
[{
printerBrand: 'Mutoh',
printerModel: 'VJ 1204G',
headsBrand: 'Epson',
headType: '',
compatibilty: [
'EDX',
'DT8',
'DT8-Pro',
'ECH',
],
cartridges: [],
},
....
]
The second array (cardridges, around 500 elements) is made of the following type of objects:
[
{
"customData": {
"brand": {
"value": {
"type": "string",
"content": "ECH"
},
"key": "brand"
},
"printer": {
"value": {
"type": "string",
"content": "c4280"
},
"key": "printer"
}
},
"name": "DT8 XLXL",
"image": {
"id": "zLaDHrgbarhFSnXAK",
"url": "https://xxxxxxx.net/images/xxxxxx.jpg"
},
"brandId": "xxxxx",
"companyId": "xxxx",
"createdAt": "2018-03-26T14:39:47.326Z",
"updatedAt": "2018-04-09T14:31:38.169Z",
"points": 60,
"id": "dq2Zezwm4nHr8FhEN"
},
...
]
What I want to do first is to is to iterate through the first array and and then iterate for all the cardridge available: if a the value customData.brand.value of a cardridge is included inside the array 'compatibility' of a printer, then I have to add this cardridge object inside the cardridges array of this printer. I have tried but somehow the iteration doesn't take place correctly. This is what I tried:
printers.forEach((printerItem) => {
const printer = printerItem;
printer.compatibilty.forEach((compatibilityItem) => {
const compatibility = compatibilityItem;
cardridges.forEach((cartridge) => {
if (compatibility === cartridge.customData.brand.value.content) {
printer.cartridges.push(cartridge);
}
});
});
});
What am I doing wrong?
You're accessing the wrong property. It should be cartridge.customData.brandName.value.content, carefully note brandName.value rather than brand.value
Your issue is that you're accessing it by the wrong property - brand and not brandName.
Furthermore, if you're targeting everything but IE, you could simplify your nested for loops to utilize some fancy ES6 array methods.
printers.forEach((p) => {
p.cartridges.push(cartridges.filter((c) => {
const brandName = c.customData.brandName.value.content;
return p.compatibilty.includes(brandName);
}));
});

Categories