Issue with JSON Schema object validation (How does it work internally)? - json

BACKGROUND:
I have mockedup my issue here for reference:
https://jsonschemalint.com/#/version/draft-06/markup/json?gist=4c185903d7aeb13f6977852a09cf5462
and I am using this npm package: https://www.npmjs.com/package/jsonschema
CODE
//i read in JSON specified in files (the contents of which are below) and parse them into JSON objects. This process works fine.
var jsonDef = JSON.parse(schemaFile); //i store this jsonDef in my database as an object
var jsonObj = JSON.parse(objFile);
var jsonv = new JSONValidator();
var validateResult = jsonv.validate(jsonObj, jsonDef); //jsonDef is read from my database
//validateResult.valid is true
PROBLEM:
I have a general schema + metadata definition like so ("props" contains the actual object schema I want to validate)
schemaFile:
{
"name":"schoolDemo",
"displayName":"School Demo",
"propertiesKey":"assetId",
"props":{
"assetId": {
"type": "string"
},
"grade": {
"type": "number"
}
}
}
objFile:
{
"assetId": "75255972",
"grade": "A"
}
However, when I try to validate against the following user-input object, it succeeds. Shouldn't it fail because:
(1) there is no "properties" element in the initial metadata+schema definition? This field seems to be required based on the examples shown here: https://www.npmjs.com/package/jsonschema
(2) the type for grade is not a number
What am I doing wrong?

The validation is passing because the schema is not well formed ("properties" is missing).
Try this instead and then the validation will fail:
{
"name": "schoolDemo",
"displayName": "School Demo",
"propertiesKey": "assetId",
"properties": {
"assetId": {
"type": "string"
},
"grade": {
"type": "number"
}
}
}

Related

Json schema validation shows no errors

I'm using Ajv version 6.10.2 to validate a simple Json schema that is separated in two files, but the thing is that I don't get the errors when doing the validation even though the json that I use to test is wrong.
This are the two parts of the schema:
root.json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://test.com/schemas/root.json",
"title": "test",
"description": "test",
"type": "object",
"properties": {
"entrypoint": { "$ref": "entrypoint.json" }
},
"additionalProperties": false,
"required": ["entrypoint"]
}
entrypoint.json
{
"$id": "http://test.com/schemas/entrypoint.json",
"description": "test object",
"type": "string"
}
I instantiate Ajv like this
import Ajv from 'ajv';
import root from './root.json';
import entrypoint from './entrypoint.json';
const ajv = new Ajv({
allErrors: true,
schemas: [
test,
entrypoint,
],
});
This is the validation call
const validate = ajv.getSchema('http://test.com/schemas/root.json');
And this is the json used to test against the schema
{
entrypoint: '',
incorrect: {}
}
It comes out as invalid but it doesn't show no errors, I've been going over it for a long time but I haven't found a reason.
Thanks in advance
Your problem is, you have no schema with the $id of http://test.com/schemas/test.json. You need to pass in the identifier (in your case, the full URI) of the schema you wish to use for validation into getSchema.
I can see you've copied from the documentation the URI shown as an example.

Why does a numeric key in the JSON Structure always get displayed first

(Cannot summarize the problem in a single statement, hence the ambiguous title)
I create a JSON structure via Angular Typescript, wherein when a user interacts with certains parts of the component the JSON Structure gets updated.
Steps
Initially, the JSON under consideration is by default set to the following:
{
"keyword": {
"value": "product",
"type": "main"
}
}
For example, a user chooses some parameter Name. Once the user complies to certain steps in the UI, the JSON structure gets updated to the following:
{
"keyword": {
"value": "product",
"type": "main"
},
"Name": {
"value": " <hasProperty> Name",
"type": "dataprop"
}
}
Once the user selects a numeric value for a parameter like dryTime, the JSON gets updated to the following:
{
"20": { // WHY WOULD 20 be here?
"value": "<hasValue> 20",
"type": "fValue"
},
"keyword": {
"value": "Varnish",
"type": "main"
},
"Name": {
"value": " <hasProperty> Name",
"type": "dataprop"
},
"dryingTime": {
"value": " <hasProperty> dryingTime",
"type": "dataprop"
}
}
I understand that a JSON is an unordered data structure. But a previous implementation of something similar actually worked well, i.e., the value 20 here was 20.0 before and it was displayed after dryingTime in my JSON.
The order is critical for me as I parse all the Keys in the above mentioned JSON using a for loop and store it in an array. This array needs to show all the keys in the order of the User Interaction.
Where am I going wrong here if I decide to stay with JSON and not with an array to store such interactions?
Yes, JSON fields are unordered. JSON array is ordered.
If you want to keep the order of elements insterted, you could build your JSON like so:
{
"keyword": {
"value": "Varnish",
"type": "main"
},
"props": [
{
"name": "dryingTime",
"value": 20
},
{
"name": "anotherOrderedField",
"value": "fieldValue"
}
]
}

Creating a type definition for a property named "type" using JSON schema

I'm trying to create a JSON schema for an existing JSON file that looks something like this:
{
"variable": {
"name": "age",
"type": "integer"
}
}
In the schema, I want to ensure the type property has the value string or integer:
{
"variable": {
"name": "string",
"type": {
"type": "string",
"enum": ["string", "integer"]
}
}
}
Unfortunately it blows up with message: ValidationError {is not any of [subschema 0]....
I've read that there are "no reserved words" in JSON schema, so I assume a type of type is valid, assuming I declare it correctly?
The accepted answer from jruizaranguren doesn't actually answer the question.
The problem is that given JSON (not JSON schema, JSON data) that has a field named "type", it's hard to write a JSON schema that doesn't choke.
Imagine that you have an existing JSON data feed (data, not schema) that contains:
"ids": [ { "type": "SSN", "value": "123-45-6789" },
{ "type": "pay", "value": "8675309" } ]
What I've found in trying to work through the same problem is that instead of putting
"properties": {
"type": { <======= validation chokes on this
"type": "string"
}
you can put
"patternProperties": {
"^type$": {
"type": "string"
}
but I'm still working through how to mark it as a required field. It may not be possible.
I think, based on looking at the "schema" in the original question, that JSON schemas have evolved quite a lot since then - but this is still a problem. There may be a better solution.
According to the specification, in the Valid typessection for type:
The value of this keyword MUST be either a string or an array. If it is an array, elements of the array MUST be strings and MUST be unique.
String values MUST be one of the seven primitive types defined by the core specification.
Later, in Conditions for successful validation:
An instance matches successfully if its primitive type is one of the types defined by keyword. Recall: "number" includes "integer".
In your case:
{
"variable": {
"name": "string",
"type": ["string", "integer"]
}
}

Access Extended Choice Parameter Script plugin parameters in Groovy script

I used Extended Choice Parameter Script plugin and created a JSON editor with Array type as below:
disable_edit_json: true,
disable_properties: true,
disable_collapse: true,
theme: "jqueryui",
iconlib:"fontawesome4",
schema: {
"type": "object",
"title": "instances",
"properties": {
"instance": {
"type": "array",
"propertyOrder" : 1,
"format": "table",
"uniqueItems": true,
"items": {
"title": "instance",
"type": "object",
"properties": {
"url": {
"type": "string"
}
}
}
}
}
}
The parameter name is "ServerUrls". Using this I can pass one or many URLs to my Jenkins job, and I want to know the size of the array and access each of these parameter values from within a Groovy script. Conceptually something like ServerUrls.instance[0], ServerUrls.instance1 etc.
Just doing println params["ServerUrls"] throws an Exception.
Can someone please help?
It worked. The solution is as below, and it returns the value as JSON in a string format. It should be fairly easy to parse the JSON to obtain the internals of it.
def hardcoded_param = "ServerUrls"
def resolver = build.buildVariableResolver
def hardcoded_param_value = resolver.resolve(hardcoded_param)
println hardcoded_param_value

Validate Swagger API Declaration using official Swagger API schema

The swagger-spec repository provides a JSON-schema describing a valid Swagger 2.0 API definition.
I would like to use this schema in order to validate if a given API definition file is valid before I try to interpret it.
I'm using the following code to load the schema using Json.NET:
JsonSchema swaggerApiSchema;
using (var textReader = new JsonTextReader(new StreamReader(#"C:\path\to\schema.json")))
{
swaggerApiSchema = JsonSchema.Read(textReader);
}
This throws an ArgumentException reporting "Can not convert Array to Boolean.".
Is there something wrong with the schema file, is this a bug with Json.NET, or am I just doing something wrong?
As per documentation, JSON.NET implements JSON Schema Draft 3. More here. But the Swagger schema you posted is created according to the JSON Schema Draft 4. One of the differences between the Draft 3 and Draft 4 of the JSON Schema is the required attribute, which in JSON Schema Draft 3 was an attribute of subschemas in properties. In JSON Schema Draft 4 is a first level keyword playing the same role, and has a string array as an argument.
Sample of JSON Schema Draft 3:
{
"properties": {
"Id": {
"required": true,
"type": "integer"
},
"FirstName": {
"required": true,
"type": "string",
},
"LastName": {
"required": true,
"type": "string
}
}
}
Sample of JSON Schema Draft 4:
{
"properties": {
"Id": {
"type": "integer"
},
"FirstName": {
"type": "string"
},
"LastName": {
"type": "string"
}
},
"required": [ "Id", "FirstName", "LastName" ]
}
Notice the difference in the two schemas, of how required properties are defined. That's why you are getting an error: "Can not convert Array to Boolean.".
And here is the first appearance of required property in the Swagger JSON Schema, that is causing the error:
"required": [ "swagger", "info", "paths" ]
I would suggest to validate with parser that implements JSON Schema Draft 4.