how to give empty for email in json - json

I need to construct json schema for email which will accept either empty or email format.
I used as follows
"emailID": {
"type": "string",
"required": false,
"format": "(^$)|email"
}
But it is not validating email id is in right format or not.
even if email is simply A or * it is accepting.
But if I remove (^$) in format it is validating perfectly
how to put both conditions

First of all: this is a draft v3 schema; it is invalid against the current draft because of your required.
Then, your requirements are quite strange: either you say that the object member is not required, or if it is present it can either be an empty string or a valid email? Something is wrong somewhere.
Not that this is not doable; it is:
"emailID": {
"type": "string",
"oneOf": [
{ "enum": [ "" ] },
{ "format": "email" }
]
}
But given your "sloppy" set of constraints I am of the opinion that something is wrong somewhere.

Related

JSONSchema - Element can appear alone or within a group

I have a JSON that looks like this:
{
"name": "Jane",
"company_name": "BrandNewStartup",
"designation": "DesignLead"
}
The name element can appear alone in the JSON as well, so the following JSON is valid too.
{
"name": "Jane"
}
But company_name and designation cannot appear if name is missing. So the following JSON should be invalid:
{
"company_name": "BrandNewStartup",
"designation": "DesignLead"
}
I have tried the following rule:
"oneOf": [
{
"required": [
"name",
"company_name",
"designation"
]
},
{
"required": [
"name"
]
}
]
However this does not seem to work (e.g this validation library raises error that the JSON should be valid to only one schema but it is valid against all).
If I change this to anyOf, the first JSON with all the 3 fields works, but when name appears alone, an error is raised that the company_name designation fields are missing.
How do I define this rule?
JSON Schema is a constraints based language. Anything you don't specify is allowed.
The required keyword means a key is required in an object, but doesn't inherintly prevent any other keys from being included.
Breaking down the schema in your question, when you have all three keys in your object, as in your first example instance, then both subschemas in oneOf would be valid.
In order to restrict the allowed properties, you need to use the additionalProperties keyword, which in your case also means you need to use the properties keyword. required has no effect on additionalProperties.
The second subschema needs to only be valid when the instance has ONLY name and no other keys. Here's a live demo using the below modified JSON Schema: https://jsonschema.dev/s/7JcUa
{
"$schema": "http://json-schema.org/draft-07/schema",
"oneOf": [
{
"required": [
"name",
"company_name",
"designation"
]
},
{
"required": [
"name"
],
"properties": {
"name": true
},
"additionalProperties": false
}
]
}

How to validate structure of json using phpleague/json-guard

I'm using Laravel 5.4 for an api and have an endpoint that accepts JSON along the lines of:
{
"input": {
"owner": "name of owner",
"content": [
]
}
}
I want to get only the JSON inside input and ensure that it is valid, both structurally and based on the content.
Using http://json-guard.thephpleague.com and their basic example from the overview page, everything comes back as valid no matter what I change as the input so I assume I am using it wrong.
From their example I have constructed the following. It passes validation. The issue is that I cannot get it to fail.
routes file
Route::post('validate', 'TestController#validateJson');
TestController#validateJson
public function validateJson()
{
$dereferencer = \League\JsonReference\Dereferencer::draft4();
$schema = json_decode('{ "properties": { "id": { "type": "string", "format": "uri" } } }');
$data = json_decode('{ "id": "https://json-guard.dev/schema#" }');
$validator = new \League\JsonGuard\Validator($data, $schema);
if ($validator->fails()) {
return response($validator->errors());
}
return response('all ok');
}
I believe I might need to use the JSON Reference and define a custom schema, but until I can fully understand the example and get it to fail, I don't want to do anything more complicated.
everything comes back as valid no matter what I change as the input so I assume I am using it wrong.
It is hard to say exactly what the issue is without seeing an example of what input you tried. Since the example schema validates that id is a string with the uri format, it should fail when you provide a string that is not a valid URI. The following example will return a format error:
<?php
require __DIR__ . '/vendor/autoload.php';
$schema = json_decode('{ "properties": { "id": { "type": "string", "format": "uri" } } }');
$data = json_decode('{ "id": "hello world" }');
$validator = new \League\JsonGuard\Validator($data, $schema);
echo json_encode($validator->errors(), JSON_PRETTY_PRINT);
There are some parts of JSON Schema that are unintuitive and you might not expect to pass.
A constraint only validates if it applies to that type. If you don't pass an object validation will pass because the properties constraint only applies to objects:
$data = null;
var_dump((new \League\JsonGuard\Validator($data, $schema))->passes()); // true
To make non object inputs fail you need to specify "type": "object". Note that this will also happen with invalid JSON, since json_decode will return null when it fails.
Validation will also pass with an empty object:
$data = json_decode('{}');
var_dump((new \League\JsonGuard\Validator($data, $schema))->passes()); // true
To make the properties required you have to use the required keyword.
I want to get only the JSON inside input and ensure that it is valid, both structurally and based on the content.
This schema should work as a starting point:
{
"type": "object",
"properties": {
"input": {
"type": "object",
"properties": {
"owner": {
"type": "string",
"minLength": 1"
},
"content": {
"type": "array"
}
},
"required": ["owner", "content"],
"additionalProperties": false
}
},
"required": ["input"],
"additionalProperties": false
}
We are requiring that the input is an object, that it has an input property and no other properties, and that input is an object with the properties owner and content. The minLength rule on owner is to prevent an empty string from passing.
I believe I might need to use the JSON Reference and define a custom schema
You can write pretty complex schemas without using JSON Reference at all. It's just a way to reuse a schema without copy and pasting. For example, you might define a 'money' schema and use that for any dollar amounts in your API.
You definitely will need to write a custom schema. The schema replaces the Laravel validation rules you would write for each endpoint otherwise.

Seggregation of Json Schema Validation and Json Validation

I have a use case where I will take a json-schema as input, validate it, then keep in my system. Later I will get json data which I need to validate with above mentioned json-schema. given the scenario, I need to do two level of validations:
1. provided json-schema is valid or not.
2. Json is valid or not.
I am using json-schema-validator jar and could find only second level of validation, couldn't find json-schema validation in documentation. for example: lets say we have below sample json-schema:
{
"title": "Person",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
}
},
"required": ["firstName", "lastName"]
}
so how to validate this json-schema itself is valid or not?
There is a working example here with the everit-org/json-schema implementation (just in case you want to use a maintained library):
How to validate a json schema against the version spec it specifies in Java
You have to validate schema against meta-schema: http://json-schema.org/draft-04/schema

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

How can i define a single, unique Key-Valuepair in JsonSchema?

The Schema should allow only the following constellation: {"status":"nok"}.
The Key must always be "status" and the value should allow "ok","nok","inProgress"
No differen or additional objects,... should be allowed
I have tried this:
{
"description": "blabla",
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ok",
"inProgress",
"nok"
],
"required": true,
"additionalItems": false
}
},
"required": true,
"additionalProperties": false
}
This works, but this scheme allows that i can send the same key/value pair twice like {"status":"nok","status":"nok"}
I would be also happy, if it would work without this "object"-container that i'm using, because to reduce overhead.
Maybe someone knows a solution, thanks
There is a more fundamental issue with that input:
{"status":"nok","status":"nok"}
mainly: that input is not valid JSON. RFC 4627, section 2.2, explicitly states that "The names within an object SHOULD be unique". And in your case, they are not.
Which means the JSON parser you use can do whatever it wants to with such an input. Some JSON APIs will grab whatever value they come upon first, other parsers will grab the last value they read, others will even coalesce values -- none of this is illegal as per the RFC.
In essence: given such input, you cannot guarantee what the output of the JSON parser will be; and as such, you cannot guarantee JSON Schema validation of such an input either.