Nested Model in Loopback API - json

I am creating an API using Loopback, and I created a model. One of the properties is "depth", and inside it, it should have 4 other number properties. So I made depth an array of numbers, but it appears like this in my fish.json file:
"depth": {
"type": [
"number"
],
"required": true
},
Here is the entire file (fish.json):
{
"name": "Fish",
"plural": "fish",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string",
"required": true
},
"scientific": {
"type": "string",
"required": true
},
"environment": {
"type": "string",
"required": true
},
"minClimate": {
"type": "number",
"required": true
},
"maxClimate": {
"type": "number",
"required": true
},
"depth": {
"type": [
"number"
],
"required": true
},
"avLength": {
"type": "number",
"required": true
},
"maxLength": {
"type": "number",
"required": true
},
"avWeight": {
"type": "number",
"required": true
},
"maxWeight": {
"type": "number",
"required": true
},
"maxAge": {
"type": "number",
"required": true
},
"description": {
"type": "string",
"required": true
},
"imageUrl": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
I have looked up in the Loopback docs, and it looks like I can use a nested model here. How would I go about changing this array to a nested model? Do I need to create a new model, and then somehow add that new model into the depth property?
Basically, I want the JSON to look like this:
"depth": {
"min": "0",
"max": "0",
"avMin": "0",
"avMax": "0"
},

You may have try this:-
"depth": {
"min": {"type": "number"},
"max": {"type": "number"},
"avMin": {"type": "number"},
"avMax": {"type": "number"}
}

Related

JSON Schema required field depending on other field value

Is it possible to make a field required/non-required depending on other field value in JSON schema?
JSON schema contains mode field. If it equals to 'release' or 'debug', the file_path is not required. If it equals to 'custom' it is required.
"mode": {
"enum": [
"debug",
"release",
"custom"
],
"id": "mode",
"required": true,
"type": "string"
},
"file_path": {
"id": "file_path",
"required": false,
"type": "string"
}
There is a solution for JSON Schema draft 7:
{
"build": {
"type": "object",
"id": "build",
"oneOf": [
{
"$ref": "#/definitions/ReleaseDebug"
},
{
"$ref": "#/definitions/Custom"
}
]
}
},
"definitions": {
"ReleaseDebug": {
"required": ["mode"],
"properties": {
"mode": {
"type": "string",
"enum": [
"debug",
"release"
],
"id": "mode"
}
}
},
"Custom": {
"required": ["mode", "file_path"],
"properties": {
"mode": {
"type": "string",
"enum": [
"custom"
],
"id": "mode"
},
"file_path": {
"type": "string",
"id": "file_path"
},
}
}
}

JSON Schema Draft-07 if-then-else required field validation does not seem correct

Using Draft-07
What I got was
valid JSON
What error I expected from audit object was
directory: String length must be greater than or equal to 2
Tried two different validators with same results
https://www.jsonschemavalidator.net/
GoLang https://github.com/xeipuuv/gojsonschema
This is my schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ISAM-Wrapper",
"description": "Validate isam wrapper json",
"type": "object",
"properties": {
"directory": {
"description": "path to location of isam file",
"type": "string",
"minLength": 2
},
"isamFile": {
"description": "isam database file",
"type": "string",
"minLength": 4
},
"isamIndex": {
"description": "isam index file",
"type": "string",
"minLength": 4
},
"port": {
"description": "port number for REST listener",
"type": "integer",
"minimum": 60410,
"maximum": 69999
},
"actions": {
"description": "Which operations are supported",
"type": "object",
"items": {
"properties": {
"create": {
"type": "boolean"
},
"read": {
"type": "boolean"
},
"update": {
"type": "boolean"
},
"delete": {
"type": "boolean"
}
}
},
"required": [
"create",
"read",
"update",
"delete"
]
},
"fields": {
"description": "each object describes one field of the isam file",
"type": "array",
"minItems": 1,
"items": {
"title": "field",
"description": "field schema",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"ordinal": {
"type": "integer",
"minimum": 0
},
"offset": {
"type": "integer",
"minimum": 0
},
"length": {
"type": "integer",
"minimum": 1
},
"dataType": {
"enum": [
"uchar",
"ulong",
"long",
"uint",
"int",
"ushort",
"short"
]
}
},
"required": [
"name",
"ordinal",
"offset",
"length",
"dataType"
]
}
},
"audit": {
"description": "input needed to enable and configure isam auditing",
"type": "object",
"items": {
"properties": {
"enable": {
"enum": [
true,
false
]
},
"directory": {
"type": "string",
"minLength": 2
},
"fileName": {
"type": "string",
"minLength": 4
},
"workDirectory": {
"type": "string",
"minLength": 2
},
"archiveDirectory": {
"type": "string",
"minLength": 2
},
"interval": {
"type": "integer",
"minimum": 1
},
"byteThreshold": {
"type": "integer",
"minimum": 1048576,
"maximum": 1073741824
}
}
},
"required": [
"enable"
],
"if": {
"not": {
"properties": {
"enable": {
"enum": [
false
]
}
}
}
},
"then": {
"required": [
"directory",
"fileName",
"workDirectory",
"archiveDirectory",
"interval",
"byteThreshold"
]
}
}
},
"required": [
"directory",
"isamFile",
"isamIndex",
"port",
"actions",
"fields",
"audit"
]
}
This is my JSON
{
"directory": "./",
"isamFile": "isam.dat",
"isamIndex": "isam.idx",
"port": 60410,
"actions": {
"create": true,
"read": true,
"update": true,
"delete": true
},
"fields": [
{
"name": "F1",
"ordinal": 0,
"offset": 0,
"length": 4,
"dataType": "ulong"
},
{
"name": "F2",
"ordinal": 1,
"offset": 4,
"length": 4,
"dataType": "ulong"
}
],
"audit": {
"enable": true,
"directory": "",
"fileName": "file",
"workDirectory": "./work",
"archiveDirectory": "./archive",
"interval": 5,
"byteThreshold": 1500000
}
}
This issue you have is that your schema is invalid. For both actions and audit you specify these as objects but you don't provide any properties. What you do do, however, is specify an items key (which does nothing here - that's a key on an array) which contains the properties.
Once you correct this error, the schema behaves as you intend, see https://repl.it/repls/BlankWellmadeFrontpage

JSON-schema: value based on oneOf

I have the following json-schema which defines 3 types of toys, to be used with this json GUI builder (github):
{
"id": "http://some.site.somewhere/entry-schema#",
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "schema for toys in game",
"type": "object",
"required": [ "type" ],
"properties": {
"sawObj": {
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/rect" },
{ "$ref": "#/definitions/circle" },
{ "$ref": "#/definitions/img" }
]
}
},
"definitions": {
"rect": {
"properties": {
"width": { "type": "integer" },
"height": { "type": "integer" },
"weight": { "type": "integer" }
},
"required": [ "width", "height", "weight" ],
"additionalProperties": false
},
"circle": {
"properties": {
"radius": { "type": "integer" },
"weight": { "type": "integer" }
},
"required": [ "radius", "weight" ],
"additionalProperties": false
},
"img": {
"properties": {
"path": { "type": "string" },
"width": { "type": "integer" },
"height": { "type": "integer" },
"weight": { "type": "integer" }
},
"required": [ "path", "width", "height", "weight" ],
"additionalProperties": false
}
}
}
If I pick the circle object for example I get an output:
{
"sawObj": {
"radius": 0,
"weight": 0
}
}
I want to add a value "type" which would always be constrained to reflect the users chosen type. So instead something like this:
{
"sawObj": {
"type": "circle",
"radius": 0,
"weight": 0
}
}
Where the type is automatically determined by the users choice from the oneOf properties section.
How can I do this with json-schema?
I was able to do this the enum value and only allowing a single value representing the type. I also set the type value as required so it is always automatically set to 'circle'.
"circle": {
"properties": {
"radius": {
"type": "integer"
},
"weight": {
"type": "integer"
},
"type": {
"type": "string",
"enum": ["circle"]
}
},
"required": ["radius", "weight", "type"],
"additionalProperties": false
}
Note: I want to point out this solution is not ideal. I'm hoping to find a better way to do this.

JSONSchema draft v3 validation error

I have created a JSON schema following the draft v3 specifications. The schema looks like this:
{
"housePolicies": {
"properties": {
"guaranteePolicies": {
"items": {
"$ref": "#/housePolicies/guaranteePolicy"
},
"type": "array"
},
"specialRequirements": {
"items": {
"$ref": "#/housePolicies/specialRequirement"
},
"type": "array"
},
"chainCode": {
"required": true,
"type": "string",
"description": "Unique identifier of the chain"
},
"losRestrictions": {
"items": {
"$ref": "#/housePolicies/losRestriction"
},
"type": "array"
},
"specialEvents": {
"items": {
"$ref": "#/housePolicies/specialEvent"
},
"type": "array"
},
"propertyCode": {
"required": true,
"type": "string",
"description": "Unique identifier of the property in the chain"
}
},
"specialRequirement": {
"id": "specialRequirement",
"properties": {
"minLOS": {
"type": "integer",
"description": "Minimum stay, in days, that applies for a special requirement restriction.\nOptional: If no input provided, there is no minimum LOS required for that period.",
"format": "int64"
},
"startDate": {
"required": true,
"type": "string",
"description": "Date when a special requirement restriction starts",
"format": "date"
},
"endDate": {
"required": true,
"type": "string",
"description": "Date when a special requirement restriction ends",
"format": "date"
}
}
},
"guaranteePolicy": {
"dow": {
"id": "dow",
"properties": {
"monday": {
"required": true,
"type": "boolean"
},
"tuesday": {
"required": true,
"type": "boolean"
},
"friday": {
"required": true,
"type": "boolean"
},
"wednesday": {
"required": true,
"type": "boolean"
},
"thursday": {
"required": true,
"type": "boolean"
},
"sunday": {
"required": true,
"type": "boolean"
},
"saturday": {
"required": true,
"type": "boolean"
}
}
},
"id": "guaranteePolicy",
"properties": {
"startDate": {
"required": true,
"type": "string",
"description": "Date when a guarantee policy starts",
"format": "date"
},
"endDate": {
"required": true,
"type": "string",
"description": "Date when a guarantee policy ends",
"format": "date"
},
"guaranteeRequiredDow": {
"items": {
"$ref": "#/housePolicies/guaranteePolicy/dow"
},
"required": true
}
}
},
"losRestriction": {
"id": "losRestriction",
"properties": {
"startDate": {
"required": true,
"type": "string",
"description": "Date when a length of stay restriction starts",
"format": "date"
},
"max": {
"type": "integer",
"description": "In case max is not provided it measn that there is no maximum length of stay restrictions.\nOptional: If no input provided, there is no maximum length restriction.",
"format": "int64"
},
"endDate": {
"required": true,
"type": "string",
"description": "Date when a length of stay restriction ends",
"format": "date"
},
"min": {
"type": "integer",
"description": "In case min is not provided it means that there is no minimum length of stay restrictions.\nOptional: If no input provided, there is no minimum length restriction.",
"format": "int64"
}
}
},
"specialEvent": {
"id": "specialEvent",
"properties": {
"startDate": {
"required": true,
"type": "string",
"description": "Date when a special event restriction starts",
"format": "date"
},
"endDate": {
"required": true,
"type": "string",
"description": "Date when a special event restriction ends",
"format": "date"
}
}
},
"id": "housePolicies"
},
"$schema": "http://json-schema.org/draft-03/schema#",
"id": "request",
"properties": {
"housePolicies": {
"items": {
"$ref": "#/housePolicies"
},
"required": true
}
}
}
I am now trying to validate some JSON against it, but jsonschemavalidator complains about the schema, giving error when resolving schema reference '#/housePolicies/guaranteePolicy/dow'. I verified in the documentation that the references are put in the proper format. Could anyone point where is the error in this schema?
You have used json-path in your $ref, but still use an id on the objects. You don't need both and they seem to be conflicting. If you remove the id's, your schema works.

How to use oneOf alongside a common sub-schema (V4)

I'm having trouble trying to create a schema that makes use of both oneOf and a common referenced sub-schema, in order to avoid having to duplicate parts of the schema.
The JSON that the schema should be validating against looks as follows:
{
"createdDate": "2015-01-20T17:10:05Z",
"createdBy": "testUser",
"lastModifiedDate": "2015-01-20T17:10:05Z",
"lastModifiedBy": "testUser",
"fileUrl": {
"path": "/path/to/file",
"fileName": "file.pdf"
},
"referenceType": "person",
"fileType": "certificate",
"personId": "12345"
}
From this, the common part is:
{
"createdDate": "2015-01-20T17:10:05Z",
"createdBy": "testUser",
"lastModifiedDate": "2015-01-20T17:10:05Z",
"lastModifiedBy": "testUser",
"fileUrl": {
"path": "/path/to/file",
"fileName": "file.pdf"
}
}
The remaining 3 fields are always the same in name and all required, but the allowed enum values for them will vary.
So the schema for the remaining 3 could be one of the following:
{
"properties": {
"referenceType": {
"type": "string",
"enum": [
"vehicle"
]
},
"fileType": {
"type": "string",
"enum": [
"registration document"
]
},
"vehicleId": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"vehicleId"
]
}
OR
{
"properties": {
"referenceType": {
"type": "string",
"enum": [
"person"
]
},
"fileType": {
"type": "string",
"enum": [
"certificate"
]
},
"personId": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"personId"
]
}
I can't seem to create a schema whereby I can avoid duplicating the common fields, and have the oneOf, and set additionalProperties to false across the whole schema.
With the below example, trying to set additionalProperties to false causes validation errors. Is it possible to do what I'm trying to do?
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"commonFile": {
"properties": {
"createdDate": {
"type": "string",
"format": "date-time"
},
"createdBy": {
"type": "string",
"pattern": "[^ ]"
},
"lastModifiedDate": {
"type": "string",
"format": "date-time"
},
"lastModifiedBy": {
"type": "string",
"pattern": "[^ ]"
},
"fileUrl": {
"type": "object",
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"pattern": "[^ ]"
},
"fileName": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"path",
"fileName"
]
}
}
}
},
"oneOf": [{
"allOf": [
{"$ref": "#/definitions/commonFile"},
{
"properties": {
"referenceType": {
"type": "string",
"enum": [
"person"
]
},
"fileType": {
"type": "string",
"enum": [
"certificate"
]
},
"personId": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"personId"
]
}
]
}, {
"allOf": [
{"$ref": "#/definitions/commonFile"},
{
"properties": {
"referenceType": {
"type": "string",
"enum": [
"vehicle"
]
},
"fileType": {
"type": "string",
"enum": [
"registration document"
]
},
"vehicleId": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"vehicleId"
]
}
]
}
],
"required": [
"createdDate",
"createdBy",
"lastModifiedDate",
"lastModifiedBy",
"fileUrl",
"referenceType",
"fileType"
]
}
I recommend not setting additionalProperties to false. It is usually best just to quietly ignore properties that are not defined. The following schema is what you would have to do to accomplish your goal.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"createdDate": { "type": "string", "format": "date-time" },
"createdBy": { "type": "string", "pattern": "[^ ]" },
"lastModifiedDate": { "type": "string", "format": "date-time" },
"lastModifiedBy": { "type": "string", "pattern": "[^ ]" },
"fileUrl": {
"type": "object",
"additionalProperties": false,
"properties": {
"path": { "type": "string", "pattern": "[^ ]" },
"fileName": { "type": "string", "pattern": "[^ ]" }
},
"required": ["path", "fileName"]
},
"referenceType": { "type": "string" },
"fileType": { "type": "string" },
"personId": {},
"vehicleId": {}
},
"additionalProperties": false,
"anyOf": [
{
"properties": {
"referenceType": { "enum": ["person"] },
"fileType": { "enum": ["certificate"] },
"personId": { "type": "string", "pattern": "[^ ]" }
},
"required": ["personId"],
"not" : { "required": ["vehicleId"] }
},
{
"properties": {
"referenceType": { "enum": ["vehicle"] },
"fileType": { "enum": ["registration document"] },
"vehicleId": { "type": "string", "pattern": "[^ ]" }
},
"required": ["vehicleId"],
"not" : { "required": ["personId"] }
}
],
"required": ["createdDate", "createdBy", "lastModifiedDate", "lastModifiedBy", "fileUrl", "referenceType", "fileType"]
}
The first thing I did was remove all the extraneous allOfs. Only one anyOf is needed. I defined the common properties in the main schema. The variations are described in the anyOf clause.
If you set additionalProperties to false, an additional schema (such as allOf, oneOf, and anyOf) can not introduce new properties. This means that all properties that are going to be allowed in this schema must be included in the schema that declares additionalProperties to be false. That is why I declared referenceType, fileType, personId, and vechicleId in the main schema.
The problem now is that additionalProperties no longer excludes vehicleId when referenceType is person or personId when referenceType is vehicle. To make sure this isn't allowed, I added the not clauses.
If were you add a third variation, restricting additional properties gets even more difficult. It's not just adding an additional referenceType to the anyof schema array. You also have to add new properties to the main schema and disallow those new types for all of the existing referenceTypes. You have to make changes all over the schema instead of just the area that is changing. This is why setting additionalProperties to false is generally not the best idea.