JSON schema validation for base64 string is not working - json

I am using following schema to validate image base64 string:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"image": {
"type": "string",
"media": {
"contentEncoding": "base64",
"oneOf": [
{ "mediaType": "image/png" },
{ "mediaType": "image/jpg" },
{ "mediaType": "image/jpeg" }
]
}
}
},
"required": [
"image"
]
}
But the schema is not working, any string, even invalid, is passed to application
I am using JSON Schema for PHP to validate json input
UPDATE
This what I tried to change, but it doesn't work
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"image": {
"title": "image",
"type": "string",
"media": {
"binaryEncoding": "base64",
"type": "image/png"
}
}
},
"required": [
"image"
]
}

Your problem is old syntax which is no longer supported in JSON Hyper-Schema Draft #4. It changed contentEncoding into binaryEncoding (see the change log here).
A relevant excerpt from the spec follows:
"imgData": {
"title": "Article Illustration (small)",
"type": "string",
"media": {
"binaryEncoding": "base64",
"type": "image/png"
}
}
Also, you mentioned nothing about which validator you're using. It may prove important, as compliance across different implementations may vary.
Update: Also, the $schema should be http://json-schema.org/draftv4/hyper-schema for hyper-schema processing.

Related

Unique value for a property validation using json schema

I have a JSON object like:
{
"result": [
{
"name" : "abc",
"email": "abc.test#mail.com"
},
{
"name": "def",
"email": "def.test#mail.com"
},
{
"name": "xyz",
"email": "abc.test#mail.com"
}
]
}
and schema for this:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/object1607582431.json",
"title": "Root",
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"$id": "#root/result",
"title": "Result",
"type": "array",
"default": [],
"uniqueItems": true,
"items": {
"$id": "#root/result/items",
"title": "Items",
"type": "object",
"required": [
"name",
"email"
],
"properties": {
"name": {
"$id": "#root/result/items/name",
"title": "Name",
"type": "string"
},
"email": {
"$id": "#root/result/items/email",
"title": "Email",
"type": "string"
}
}
}
}
}
}
I am looking for an option to check uniqueness for email irrespective of name. How I can validate that every email should be unique?
You can't. There are no keywords that let you compare one particular data value against another, other than uniqueItems, which compares an array element in toto against another.
The JsonSchema specification does not currently support this.
You can see the active GitHub issue here: https://github.com/json-schema-org/json-schema-vocabularies/issues/22
However, there are various extensions of JsonSchema that do validate unique fields within lists of objects.
If you happen to be using Python you can use the package (I created) JsonVL. It can be installed with pip install jsonvl and then run with jsonvl data.json schema.json.
Code examples in the GitHub repo: https://github.com/gregorybchris/jsonvl

Conditionally Merging JSON Schema Properties

I'm trying to create a JSON schema to validate YAML for some VSCode intellisense. What I'm trying to do is choose the correct subschema to use for a property in the main schema based on an adjacent key's value.
Some JSON examples:
[
{
"name": "doesntmatter",
"matchMe": "stringToMatch:123whatever",
"mergeMe": {
"key1": "value1",
"key2": "value2"
}
}
]
[
{
"name": "doesntmatter",
"matchMe": "anotherStringToMatch:123whatever",
"mergeMe": {
"anotherKey": "valueSomething",
"anotherKey2": "cheese"
}
}
]
So I need to choose the correct schemas for the mergeMe objects based on the substring match of matchMe. After following a bunch of answers, I'm at a point where I can either make it match multiple, and error my linter, or match none, but an online validator says it's ok (except nothing matches as the required fields aren't triggering).
I moved my sub-schemas to be merged into definitions to reference them, and then used an if/then to match. That worked with one, but then I tried to expand it to do the tree matching, and I can't get that to work. Someone said that I should wrap my if/thens in an allOf (I'm not sure why that would work since surely not all of them would match?). Changing it to an anyOf makes none of them match and I get no intellisense. Nor do I really understand why I should wrap single if/thens or thens in allOfs.
The idea is that based on the pattern it uses a definitions schema to match the mergeMe property, but the conditional logic isn't quite right. Thinned schema below:
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/example.json",
"type": "array",
"title": "The root schema",
"description": "The root schema comprises the entire JSON document.",
"default": [],
"additionalItems": true,
"definitions": {
"stringToMatch": {
"$id": "#/definitions/stringToMatch",
"type": "object",
"properties": {
"key1": {
"type": "string"
}
},
"required": [
"key1"
],
"additionalProperties": true
},
"anotherStringToMatch": {
"$id": "#/definitions/anotherStringToMatch",
"type": "object",
"properties": {
"key2": {
"type": "string"
}
},
"required": [
"key2"
],
"additionalProperties": true
}
},
"items": {
"$id": "#/items",
"type": "object",
"title": "main schema",
"description": "An explanation about the purpose of this instance.",
"default": {},
"examples": [],
"required": [
"name",
"matchMe",
"mergeMe"
],
"properties": {
"name": {
"$id": "#/items/name",
"type": "string",
"title": "The name schema",
"description": "An explanation about the purpose of this instance.",
"default": "",
"examples": []
},
"matchMe": {
"$id": "#/items/matchMe",
"type": "string",
"title": "The matchMe schema",
"description": "An explanation about the purpose of this instance.",
"default": "",
"examples": []
}
},
"allOf": [
{
"if": {
"properties": {
"matchMe": {
"pattern": "^stringToMatch:[0-9.]+"
}
}
},
"then": {
"allOf": [
{
"type": "object",
"properties": {
"mergeMe": {
"$ref": "#/definitions/stringToMatch"
}
}
}
]
}
},
{
"if": {
"properties": {
"gear": {
"pattern": "^anotherStringToMatch:[0-9.]+"
}
}
},
"then": {
"allOf": [
{
"type": "object",
"properties": {
"mergeMe": {
"$ref": "#/definitions/anotherStringToMatch"
}
}
}
]
}
}
],
"additionalProperties": true
}
}
What I want in JS would look something like
const schema = { name, matchMe }
if (matchMe == "string1") schema.mergeMe = ...subschema1;
else if (...)
else if (...)
but I just can't really work it out. Can someone help?
Edit: jsonschema.dev playground - the idea being if I specify the food as prefixed by "fruit" I have to give it "pips" and "berry", whereas if I specify "vegetable" I have to give it a totally differet schema, and they don't overlap.
https://jsonschema.dev/s/pHzGo
This actually ended up being a bug in the VSCode YAML extension that was ingesting my schema, causing the if blocks to not evaluate, and has been raised, fixed and released.

Why jsonschema is not match with the json?

Given that, I have the below json:
{
"msg":"aaaa",
"email":"aaa#gmail.com"
}
Then, I wrote the below json schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Json schema sample",
"type": "object",
"additionalProperties": true,
"required": [
"msg",
"email"
],
"properties": {
"msg": {
"type": "string"
},
"email": {
"type": "string",
"pattern": "^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,}$"
}
}
}
And sadly it is not matches with the json.
If you remove the ,"pattern": "^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,}$" which is the regular expression for checking the email, then it works well. Please test it in this website.
I am sure that my regular expression for email is fine. But I don't know why it is not working in the json schema!
The \ is also an escape character in the json string, so now it's invalid json.
You could also see that when validating the json, for example on jsonlint.com
So your pattern needs a second \:
pattern": "^[a-z0-9._%+-]+#[a-z0-9.-]+\\.[a-z]{2,}$"
Full example: (don't forget to select draft-04 on https://jsonschemalint.com/, or change the schema to draft-07)
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Json schema sample",
"type": "object",
"additionalProperties": true,
"required": [
"msg",
"email"
],
"properties": {
"msg": {
"type": "string"
},
"email": {
"type": "string",
"pattern": "^[a-z0-9._%+-]+#[a-z0-9.-]+\\.[a-z]{2,}$"
}
}
}

JSON schema - how to define types that depend on values elsewhere in file

Given that I have a JSON file something like this:
{
"organisation":"Acme Co. Ltd",
"organisation_abbreviation":"acme",
"document_types":["invoice","credit-note"],
"invoice":{
"date":"2017-05-31",
"value":238.44,
"description":"invoice for xxx"
},
"credit_note":{
"date":"2017-05-22",
"value":0.0,
"description":"DNOTE for xxx"
},
}
The salient being that in document types, I define the various permitted document types, and then later down I have a section for each of the document types named here.
How can I write a schema validation that will check that each document type section is a one of the types mentioned above (the example would fail because 'credit-note' != 'credit_note')
Would that fill what you need by using the OneOf:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Acme billing",
"type" : "object",
"definitions": {
"Entry": {
"type": "object",
"properties": {
"date": "string",
"value": "number",
"description": "string"
}
}
},
"properties": {
"organisation": "string",
"organisation_abbreviation": "string",
"document_types": {
"enum": ["invoice","credit-note"]
}
"oneOf" : [{
"properties": {
"invoice": {
"$ref" : "#/definitions/Entry"
},
"credit-note":{
"$ref" : "#/definitions/Entry"
}
]
},
"additionalProperties":false
}
}
}

JSON Schema validator with an array of specific objects (different types)

I have the following JSON data that I would like to validate.
[
{ "fieldType": "oneThing" },
{ "fieldType": "anotherThing" },
{ "fieldType": "oneThing" }
]
And my current (non working) schema is:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items": {
"oneOf": [
{ "$ref": "#/definitions/oneThing" },
{ "$ref": "#/definitions/anotherThing" }
]
},
"definitions": {
"oneThing": {
"type": "object",
"properties": {
"fieldType": {
"type": "string",
"pattern": "oneThing"
}
},
"required": [
"fieldType"
]
},
"anotherThing": {
"type": "object",
"properties": {
"fieldType": {
"type": "string",
"pattern": "anotherThing"
}
},
"required": [
"fieldType"
]
}
}
}
I'm getting the following error but I fail to see what I'm doing wrong.
[] Object value found, but an array is required
More context: I'm generating a dynamic HTML form based on a JSON configuration. The HTML form will have a specific set of valid field types and the same field type may exist multiple times in the config, thus oneThing appearing more than once in the above sample json.
As it turns out, this had nothing to do with my JSON schema but with how I was calling the library that was parsing the schema.
I'm using https://github.com/justinrainbow/json-schema and was passing the wrong data type to the class. Duh!