I'm validating a json scheme where I need to check if the json has an array of 'activities', and if not, if it has a 'live' attribute which must be true.
My schema is quite simple note the enum is not working
const viewSchema = {
"type": "object",
"anyOf": [
{"required": ["live"]},
{"required": ["activities"]}
],
"properties":{
"title": {"type": "string"},
"live": {"type": "boolean", "enum": [ true ]},
"activities": {"type": "array"}
}
So I am trying to validate against the following
isValid({title: 'a title'}) // false: activities or live required
isValid({title: 'a title', activities: []}) // true
isValid({title: 'a title', live: true}) // true
isValid({title: 'a title', live: false) // true - this should be false
It's a little redundant, but you can use oneOf and two distinct schema to achieve this.
Here's an example using AJV:
// Code goes here
var ajv = new Ajv({
$data: true,
verbose: true
});
let schema = {
"type": "object",
"oneOf": [{
"type": "object",
"properties": {
"live": {
"type": "boolean",
"enum": [true]
},
},
"required": ["live"]
},
{
"type": "object",
"properties": {
"activities": {
"type": "array"
}
},
"required": ["activities"]
}
]
};
ajv.validate(schema, {
title: 'a title'
}) // false: activities or live required
console.log('ERRORS: ', this.ajv.errors)
ajv.validate(schema, {
title: 'a title',
activities: []
}) // true
console.log('ERRORS: ', this.ajv.errors)
ajv.validate(schema, {
title: 'a title',
live: true
}) // true
console.log('ERRORS: ', this.ajv.errors)
ajv.validate(schema, {
title: 'a title',
live: false
}) // this is now invalid
console.log('ERRORS: ', this.ajv.errors)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/5.3.0/ajv.bundle.js"></script>
Related
I'm trying to bump an exact query first using Specification and Pageable from spring data.
When making a request to this endpoint http://localhost:8080/configs?search=PATH
This is the response now:
{
"content": [
{
"groupId": "PATHOD",
"type": "company",
},
{
"groupId": "PATH",
"type": "company",
},
{
"groupId": "APATH",
"type": "company",
}
],
"pageable": {
...
},
"sort": {
"sorted": true,
"unsorted": false,
"empty": false
},
"size": 10,
"empty": false
}
I want to be like, with the exact match bumped to first place:
{
"content": [
{
"groupId": "APATH",
"type": "company",
},
{
"groupId": "PATH",
"type": "company",
},
{
"groupId": "PATHOD",
"type": "company",
}
],
"pageable": {
....
},
"sort": {
"sorted": true,
"unsorted": false,
"empty": false
},
"size": 10,
"empty": false
}
This is my code right now, but I don't know how to write the specification
fun findAllWithFilters(
exactMatchFirst: Boolean = false,
pageable: Pageable
): Page<OrderConfig> {
val spec = and(
withExactMatchFirst(exactMatchFirst)
)
return findAll(spec, pageable)
}
The PATH groupId should be the first one to appear in the results
My login has different payloads one is:
{
"username": "",
"pass": ""
}
And one of the other is:
{
"username": "",
"pass": "",
"facebook": true
}
And the last:
{
"username": "",
"pass": "",
"google": true
}
My schema is as follow:
login_schema = {
"title": "UserLogin",
"description": "User login with facebook, google or regular login.",
"type": "object",
"properties": {
"username": {
"type": "string"
},
"pass": {
"type": "string"
},
"facebook": {
"type": "string"
},
"google": {
"type": "string"
}
},
"oneOf": [
{
"required": [
"username",
"pass"
],
"additionalProperties": False,
},
{
"required": [
"username",
"pass"
"google"
]
},
{
"required": [
"username",
"pass",
"facebook"
]
}
],
"minProperties": 2,
"additionalProperties": False,
}
It should give an error for the below sample:
{
"username": "",
"pass": "",
"google": "",
"facebook": ""
}
But it validates the schema successfully! What I have done wrong in the above schema?
EDIT-1:
pip3 show jsonschema
Name: jsonschema
Version: 3.0.2
Summary: An implementation of JSON Schema validation for Python
Home-page: https://github.com/Julian/jsonschema
Author: Julian Berman
Author-email: Julian#GrayVines.com
License: UNKNOWN
Location: /usr/local/lib/python3.7/site-packages
Requires: setuptools, six, attrs, pyrsistent
EDIT-2:
What I get as an error is:
jsonschema.exceptions.ValidationError: {'username': '', 'pass': '', 'google': '12'} is valid under each of {'required': ['username', 'pass', 'google']}, {'required': ['username', 'pass']}
A live demo of the error: https://jsonschema.dev/s/mXg5X
Your solution is really close. You just need to change /oneOf/0 to
{
"properties": {
"username": true,
"pass": true
},
"required": ["username", "pass"],
"additionalProperties": false
}
The problem is that additionalProperties doesn't consider the required keyword when determining what properties are considered "additional". It considers only properties and patternProperties. When just using required, additionalProperties considers all properties to be "additional" and the only valid value is {}.
However, I suggest a different approach. The dependencies keyword is useful in these situations.
{
"type": "object",
"properties": {
"username": { "type": "string" },
"pass": { "type": "string" },
"facebook": { "type": "boolean" },
"google": { "type": "boolean" }
},
"required": ["username", "pass"],
"dependencies": {
"facebook": { "not": { "required": ["google"] } },
"google": { "not": { "required": ["facebook"] } }
},
"additionalProperties": false
}
I'm building a schema that has a property with an enum and uses a oneOf to add properties and restrictions for each case of the enum. I'm getting an error about a missing property that is definitely not missing.
A reduced version of the schema:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://rc2.io/something",
"title": "Rc2 Compute Messages",
"type": "object",
"minProperties": 2,
"properties": {
"msg": {
"type": "string",
"description": "the command to perform",
"enum": ["close", "execScript"]
},
"argument": {
"type": "string",
"description": "main argument for the command"
}
},
"required": ["msg", "argument"],
"oneOf": [
{
"properties": {
"argument": { "maxLength": 0 },
"msg": { "const": "close"}
}
},
{
"properties": {
"msg": { "const": "execScript"},
"argument": { "minLength": 1 },
"queryId": { "type": "number", "multipleOf": 1.0, "minimum": 1 } },
"required": ["queryId"]
}
]
}
The json I'm trying to validate:
{
"queryId:": 2,
"argument": "testVar<-22",
"msg": "execScript"
}
The output from ajv:
[
{
keyword: 'maxLength',
dataPath: '.argument',
schemaPath: '#/oneOf/0/properties/argument/maxLength',
params: { limit: 0 },
message: 'should NOT be longer than 0 characters'
},
{
keyword: 'required',
dataPath: '',
schemaPath: '#/oneOf/1/required',
params: { missingProperty: 'queryId' },
message: "should have required property 'queryId'"
},
{
keyword: 'oneOf',
dataPath: '',
schemaPath: '#/oneOf',
params: { passingSchemas: null },
message: 'should match exactly one schema in oneOf'
}
]
Why is it not recognizing queryId?
Maybe because of this simple typo "queryId:" in your JSON data? Please note the extra colon after queryId.
There is Project model
{
"name": "Project",
"plural": "Projects",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"title": {
"type": "string",
"required": true
},
"description": {
"type": "string"
},
"code": {
"type": "string"
},
"startDate": {
"type": "date",
"required": true
},
"endDate": {
"type": "date"
},
"value": {
"type": "number"
},
"infoEN": {
"type": "string"
},
"infoRU": {
"type": "string"
},
"infoAM": {
"type": "string"
},
"externalLinks": {
"type": [
"string"
]
}
},
"validations": [],
"relations": {
"industry": {
"type": "belongsTo",
"model": "Industry",
"foreignKey": "",
"options": {
"nestRemoting": true
}
},
"service": {
"type": "belongsTo",
"model": "Service",
"foreignKey": "",
"options": {
"nestRemoting": true
}
},
"tags": {
"type": "hasAndBelongsToMany",
"model": "Tag",
"foreignKey": "",
"options": {
"nestRemoting": true
}
}
},
"acls": [],
"methods": {}
}
And it hasAndBelongsToMany tags
here is Tag model
{
"name": "Tag",
"plural": "Tags",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
Now when the relation is created loopback api gives this api endpoint.
POST /Projects/{id}/tags
This creates a new tag into the tags collection and adds it to the project.
But what about adding an already existing tag to the project?
So I figured maybe I add before save hook to the Tag
Here I'll check if the tag exists and then pass the existing one for the relation.
Something like this.
tag.js
'use strict';
module.exports = function(Tag) {
Tag.observe('before save', function(ctx, next) {
console.log(ctx.instance);
Tag.find({name: ctx.instance.name})
next();
});
// Tag.validatesUniquenessOf('name', {message: 'name is not unique'});
};
#HaykSafaryan it just demo to show you how to use tag inside project
var app = require('../../server/server');
module.exports = function(project) {
var tag=app.models.tags
//afterremote it just demo. you can use any method
project.afterRemote('create', function(ctx, next) {
tag.find({name: ctx.instance.name},function(err,result)){
if(err) throw err;
next()
}
});
};
this is just example code to show you how to use update,create ,find ,upsertwithwhere etc. tag for validation you have to setup condition over here it will not take validation which you defined in tags models
I would like to be able to maintain different stores from the same json where the model for each store is the same. Each store would need to be updated based on its root property assignment. Please see below for a sample json, store, and model, in which case each store would be updated based on the json's root property value (category 1, category 2, etc.). The goal is to be able to bind a nested list in my application to different stores on the fly, rather than call setProxy to change the url setting on a single store. Also, the json needs to be in this format. Thanks for your help and please let me know if I can provide clarification or answer any questions.
Json:
{
"items": [
{
"name": "category 1",
"status": "",
"displaytext": "",
"items": [
{
"name": "",
"status": "",
"displaytext": "",
"items": [
{
"name": "",
"status": "",
"displaytext": "",
"items": [
{
"name": "",
"status": "",
"displaytext": "",
"leaf": true
}
]
}
]
}
]
},
{
"name": "category 2",
"status": "",
"displaytext": "",
"items": [
{
"name": "",
"status": "",
"displaytext": "",
"items": [
{
"name": "",
"status": "",
"displaytext": "",
"leaf": true
}
]
}
]
},
{
"name": "cateory 3",
"status": "",
"displaytext": "",
"items": []
},
{
"name": "category 4",
"status": "",
"displaytext": "",
"items": []
}
]
}
Model:
Ext.define('MyApp.model.myModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'name',
type: 'string'
},
{
name: 'status',
type: 'string'
},
{
name: 'displaytext',
type: 'string'
}
]
}
});
Store 1, 2, 3, etc:
Ext.define('MyApp.store.storeCategory1', {
extend: 'Ext.data.TreeStore',
requires: [
'MyApp.model.myModel'
],
config: {
model: 'MyApp.model.myModel',
storeId: 'myStore',
autoLoad: false,
proxy: {
type: 'ajax',
url: '/path/to/file.json',
reader: {
type: 'json',
rootProperty: 'items'
}
}
}
});
I think you best bet would be to make a server request independent of the Store's proxy. On success, split up the data into the different stores as needed. It's fine to preprocess data this way, especially if you need to split one large data response into multiple data stores. For example:
Ext.Ajax.request({
url: 'path/to/file.json',
success: function(response){
// process server response here
var json = Ext.decode(response.responseText);
for(var i=0, l=json.items.length, i<l; i++){
// start distributing the data to your different stores here
}
}
});
Hope this helps.