how to limit the additions field in jsonschema where they is undeclare - python

In json object some field is not what i need,but they still through my validation,like below.
The jsonchemaļ¼š
my_schema = {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["endpoint", "bucket"],
"properties": {
"endpoint": {
"type": "string"
},
"bucket": {
"type": "string",
"minLength": 1
},
"dir": {
"type": "string",
"minLength": 1
}
}
}
}
The jsons:
one = [{
"endpoint": "",
"bucket": "2020-10-27 16:20:24",
"dir": "/tmp"
}]
two = [{
"endpoint": "",
"bucket": "2020-10-27 16:20:24",
"dir": "/tmp",
"id": "leaking"
}]
And i run this code in python2.7:
import jsonschema
from jsonschema import validate
print(jsonschema.__version__)
validate(instance=one, schema=my_schema)
validate(instance=two, schema=my_schema) # how can i let this line raise a Exception?
print("validated one, two.")
Output:
3.2.0
passed one, two. # this not my intention
The foregoing json two have a field "id" need to be excluded, and any fields not declared in "properties" are treated the same way.

Use additionalProperties
The additionalProperties keyword is used to control the handling of extra stuff, that is, properties whose names are not listed in the properties keyword. By default any additional properties are allowed.
The additionalProperties keyword may be either a boolean or an object. If additionalProperties is a boolean and set to false, no additional properties will be allowed.
From docs
Your schema would look like:
{
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["endpoint", "bucket"],
"properties": {
"endpoint": {
"type": "string"
},
"bucket": {
"type": "string",
"minLength": 1
},
"dir": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": false
}
}

Related

Get only content in schema builder

I am trying to build schema from my json response. and I am trying to access only content from schema builder, I don't want to access any other data from it.
full_response
{
"$schema": "http://json-schema.org/schema#",
"anyOf": [
{
"type": "object"
},
{
"type": "array",
"items": {
"type": "object",
"properties": {
"response": {
"type": "integer"
},
"content": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"title": {
"type": "string"
},
},
"required": [
"id",
"title"
]
}
}
},
"required": [
"content",
"response"
]
}
}
]
}
as you can see in response it shows all the data and I want to access only of content. But when I do it like
builder.add_schema({"type": "object", "properties": {},accitionalProperties": False})
builder.add_object(json)
builder.to_schema()
I have also tried by defining it like
builder.to_schema().content
but it says
AttributeError: 'str' object has no attribute 'content'
It is still showing everything.
I have tried many times but it still not showing. Any help would be much Appreciated. Thank You in Advance.

Why is JSON-validation always successful using this schema containing 'allOf'?

I have a JSON schema with which I want to validate some data, using python and the jsonschema module. However, this doesn't quite work as expected, as some of the accepted data doesn't appear valid at all (to me and the purpose of my application). Sadly, the schema is provided, so I can't change the schema itself - at least not manually.
This is a shortened version of the schema ('schema.json' in code below):
{
"type": "object",
"allOf": [
{
"type": "object",
"allOf": [
{
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
}
}
},
{
"type": "object",
"properties": {
"language": {
"type": "integer"
}
}
}
]
},
{
"type": "object",
"properties": {
"addressArray": {
"type": "array",
"items": {
"type": "object",
"properties": {
"streetNumber": {
"type": "string"
},
"street": {
"type": "string"
},
"city": {
"type": "string"
}
}
}
}
}
}
]
}
This is an example of what should be a valid instance ('person.json' in code below):
{
"firstName": "Sherlock",
"lastName": "Holmes",
"language": 1,
"addresses": [
{
"streetNumber": "221B",
"street": "Baker Street",
"city": "London"
}
]
}
This is an example of what should be considered invalid ('no_person.json' in code below):
{
"name": "eggs",
"colour": "white"
}
And this is the code I used for validating:
from json import load
from jsonschema import Draft7Validator, exceptions
with open('schema.json') as f:
schema = load(f)
with open('person.json') as f:
person = load(f)
with open('no_person.json') as f:
no_person = load(f)
validator = Draft7Validator(schema)
try:
validator.validate(person)
print("person.json is valid")
except exceptions.ValidationError:
print("person.json is invalid")
try:
validator.validate(no_person)
print("no_person.json is valid")
except exceptions.ValidationError:
print("no_person.json is invalid")
Result:
person.json is valid
no_person.json is valid
I expected no_person.json to be invalid. What can there be done to have only data such as person.json to be validated successfully? Thank you very much for your help, I'm very new to this (spent ages searching for an answer).
This is work schema and pay attention on "required" (when there is no such key - if field is doesn't get it just skipped):
{
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"language": {
"type": "integer"
},
"addresses": {
"type": "array",
"items": {
"type": "object",
"properties": {
"streetNumber": {
"type": "string"
},
"street": {
"type": "string"
},
"city": {
"type": "string"
}
},
"required": [
"streetNumber",
"street",
"city"
]
}
}
},
"required": [
"firstName",
"lastName",
"language",
"addresses"
]
}
I've got:
person.json is valid
no_person.json is invalid
If you have hardest structure of response (array of objects, which contain objects etc) let me known

Edit Json schema with python

I have the main Json-schema. It looks like that:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"listInfo": {
"type": "object",
"properties": {
"limit": {
"type": "integer"
},
"count": {
"type": "integer"
}
},
"required": [
"offset",
"count"
]
},
"items": {
"type": ["array", "null"],
"items": {
"type": "object",
"properties": {
"startDate": {
"type": "string"
},
"customer": {
"type": "object",
"properties": {
"customerId": {
"type": "integer"
},
"name": {
"type": "string"
}
},
"required": [
"customerId",
"name"
]
}
},
"required": [
"startDate",
"customer"
]
}
}
},
"required": [
"listInfo",
"items"
]
}
Every time after sending a get query to a host I check Json on a validation with my schema.
But Sometimes I need not all fields in it. For example I can add "&fields=startDate" in the end of my GET query.
How I can generate new Json schema for my new data (I need to automatically delete lines about "customer" in my old Json schema and generate a new json-schema file)?

python jsonschema validation using schema list

I'm trying to validate a json file against a schema using python and jsonschema module. My schema is made up from a list of schemas, one of them has definitions of basic elements and the rest are collections of these elements and other objects.
I can't find the documentation for function which loads the list of schemas so that I can validate using it. I tried separating schemas into a dictionary and calling the appropriate one on a jsonObject, but that doesn't work since they cross reference each other.
How do I load/assemble all schemas into one for validation?
Part of the schema I'm trying to load:
[{
"definitions": {
"location": {
"required": [
"name",
"country"
],
"additionalProperties": false,
"properties": {
"country": {
"pattern": "^[A-Z]{2}$",
"type": "string"
},
"name": {
"type": "string"
}
},
"type": "object"
}
},
"required": [
"type",
"content"
],
"additionalProperties": false,
"properties": {
"content": {
"additionalProperties": false,
"type": "object"
},
"type": {
"type": "string"
}
},
"type": "object",
"title": "base",
"$schema": "http://json-schema.org/draft-04/schema#"
},
{
"properties": {
"content": {
"required": [
"address"
],
"properties": {
"address": {
"$ref": "#/definitions/location"
}
},
"type": {
"pattern": "^person$"
}
}
}]
And the json object would look something like this:
{
"type":"person",
"content":{
"address": {
"country": "US",
"name" : "1,Street,City,State,US"
}
}
}
You can only validate against one schema at a time, but that schema can reference ($ref) external schemas. These references are usually URIs that can be used to GET the schema. A filepath might work too if your schemas are not public. Using a fixed up version of your example, this would look something like this ...
http://your-domain.com/schema/person
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Person",
"allOf": [{ "$ref": "http://your-domain.com/schema/base#" }],
"properties": {
"type": { "enum": ["person"] },
"content": {
"properties": {
"address": { "$ref": "http://your-domain.com/schema/base#/definitions/location" }
},
"required": ["address"],
"additionalProperties": false
}
}
}
http://your-domain.com/schema/base
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "base",
"type": "object",
"properties": {
"content": { "type": "object" },
"type": { "type": "string" }
},
"required": ["type", "content"],
"additionalProperties": false,
"definitions": {
"location": {
"type": "object",
"properties": {
"country": {
"type": "string",
"pattern": "^[A-Z]{2}$"
},
"name": { "type": "string" }
},
"required": ["name", "country"],
"additionalProperties": false
}
}
}
Some documentation that might be useful
https://python-jsonschema.readthedocs.org/en/latest/validate/#the-validator-interface
https://python-jsonschema.readthedocs.org/en/latest/references/
Instead of hand coding a single schema from all your schemata, you can create a small schema which refers to the other schema files. This way you can use multiple existing JSONschema files and validate against them in combination:
import yaml
import jsonschema
A_yaml = """
id: http://foo/a.json
type: object
properties:
prop:
$ref: "./num_string.json"
"""
num_string_yaml = """
id: http://foo/num_string.json
type: string
pattern: ^[0-9]*$
"""
A = yaml.load(A_yaml)
num_string = yaml.load(num_string_yaml)
resolver = jsonschema.RefResolver("",None,
store={
"http://foo/A.json":A,
"http://foo/num_string.json":num_string,
})
validator = jsonschema.Draft4Validator(
A, resolver=resolver)
try:
validator.validate({"prop":"1234"})
print "Properly accepted object"
except jsonschema.exceptions.ValidationError:
print "Failed to accept object"
try:
validator.validate({"prop":"12d34"})
print "Failed to reject object"
except jsonschema.exceptions.ValidationError:
print "Properly rejected object"
Note that you may want to combine the external using one of the schema cominators oneOf, allOf, or anyOf to combine your schemata like so:
[A.yaml]
oneOf:
- $ref: "sub-schema1.json"
- $ref: "sub-schema2.json"
- $ref: "sub-schema3.json"

How can I allow only the dictionary keys "source", "dest" and "keep" (see: config.json below) as dictionary keys in json schema?

How can I allow only the dictionary keys "source", "dest" and "keep" (see: config.json below) as dictionary keys in json schema?
Using "required": ["snapshots"] together with "additionalProperties": False I managed to allow only the key "snapshots", but doing that analogous for the dictionary value of the key "string" ("required": ["source","dest", "keep"]) didn't add the desired constraints to my json config.
I tested latter, by changing e.g. the key "source" to "somethingElse" in my config.json file, but jsonschema.validate() didn't raise any errors, though I expected it to.
schemaTest.py:
import json
from jsonschema import validate
schema = {
"$schema": "http://json-schema.org/schema",
"required": ["snapshots"],
"additionalProperties": False,
"properties":
{
"snapshots":
{
"type": "object",
"properties":
{
"string":
{
"type": "object",
"items": { "type": "string" },
"uniqueItems": True,
"properties":
{
"source": {"type": "string"},
"dest": {"type": "string"},
"keep": {"type": "string"}
},
"required": ["source","dest", "keep"],
"additionalProperties": False
}
}
}
}
}
path = "/home/user/test/config.json"
jsonConfig = json.load(open(path))
print(validate(jsonConfig, schema))
config.JSON:
{
"snapshots":
{
"#snapshot1":
{
"source": "/mnt/subvolContainer/#snapshot1",
"dest": "/mnt/subvolContainer/",
"keep": "w=10,m=10"
},
"#snapshot2":
{
"source": "/mnt/subvolContainer/#snapshot2",
"dest": "/mnt/subvolContainer/",
"keep": "w=10,m=10"
}
}
}
You have some extra layers of nesting inside the definition of your snapshot object. string, for example, is not a property name you are using. To validate properties of the children of unknown keys in an object, you need to put your types inside the additionalProperties object. items and uniqueItems apply to arrays, not objects.
This works:
schema = {
"$schema": "http://json-schema.org/schema",
"required": ["snapshots"],
"additionalProperties": False,
"properties":
{
"snapshots":
{
"type": "object",
"additionalProperties":
{
"type": "object",
"properties":
{
"source": {"type": "string"},
"dest": {"type": "string"},
"keep": {"type": "string"}
},
"required": ["source","dest", "keep"],
"additionalProperties": False
}
}
}
}

Categories

Resources