Skip to content

Commit 860194f

Browse files
committed
Add json schema validation feature
1 parent 5a4d7a5 commit 860194f

File tree

10 files changed

+222
-37
lines changed

10 files changed

+222
-37
lines changed

.travis.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ language: python
22
python:
33
- "3.8"
44
install: "pip install -r requirements-dev.txt"
5-
script: invoke test build docs
5+
script:
6+
- invoke style-check
7+
- invoke lint
8+
- invoke test
9+
- invoke docs
610
deploy:
711
provider: pypi
812
user: nottyo
@@ -12,4 +16,3 @@ deploy:
1216
tags: true
1317
distributions: dist
1418
repo: robotframework-thailand/robotframework-jsonlibrary
15-

JSONLibrary/jsonlibrary.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import io
33
import json
44
import os.path
5+
import jsonschema
56
from copy import deepcopy
67
from robot.api import logger
78
from robot.utils.asserts import fail
@@ -238,7 +239,7 @@ def dump_json_to_file(self, dest_file, json_object, encoding=None):
238239
Export the JSON object to a file
239240
240241
Examples:
241-
| Dump JSON To File | ${OUTPUTID)${/}output.json | ${json} |
242+
| Dump JSON To File | ${OUTPUT_DIR)${/}output.json | ${json} |
242243
"""
243244
json_str = self.convert_json_to_string(json_object)
244245
with open(dest_file, "w", encoding=encoding) as json_file:
@@ -280,3 +281,38 @@ def should_not_have_value_in_json(self, json_object, json_path):
280281
pass
281282
else:
282283
fail(f"Match found for parent {json_path}: {rv}")
284+
285+
def validate_json_by_schema_file(
286+
self, json_object, path_to_schema, encoding=None
287+
) -> None:
288+
"""Validate json object by json schema file.
289+
Arguments:
290+
- json_object: json as a dictionary object.
291+
- json_path: path to file with json schema
292+
293+
Fail if json object does not match the schema
294+
295+
Examples:
296+
| Simple | Validate Json By Schema File | {"foo":bar} | ${CURDIR}${/}schema.json |
297+
"""
298+
with open(path_to_schema, encoding=encoding) as f:
299+
self.validate_json_by_schema(json_object, json.load(f))
300+
301+
@staticmethod
302+
def validate_json_by_schema(json_object, schema) -> None:
303+
"""Validate json object by json schema.
304+
Arguments:
305+
- json_object: json as a dictionary object.
306+
- schema: schema as a dictionary object.
307+
308+
Fail if json object does not match the schema
309+
310+
Examples:
311+
| Simple | Validate Json By Schema | {"foo":bar} | {"$schema": "https://schema", "type": "object"} |
312+
"""
313+
try:
314+
jsonschema.validate(json_object, schema)
315+
except jsonschema.ValidationError as e:
316+
fail(f"Json does not match the schema: {e.schema}")
317+
except jsonschema.SchemaError as e:
318+
fail(f"Json schema error: {e}")

acceptance/JSONLibrary.robot

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,37 @@ TestConvertJSONToString
8686
TestDumpJSONToFile
8787
[Documentation] Dumps JSON to file
8888
Dump JSON to file ${TEMPDIR}/sample_dump.json ${json_obj_input}
89-
File Should Exist ${TEMPDIR}/sample_dump.json
89+
File Should Exist ${TEMPDIR}/sample_dump.json
90+
91+
TestValidateJsonBySchemaFile
92+
[Documentation] Validate JSON by schema file
93+
Validate Json By Schema File ${json_obj_input} ${CURDIR}${/}..${/}tests${/}json${/}example_schema.json
94+
95+
TestValidateJsonBySchema
96+
[Documentation] Validate JSON by schema
97+
${schema} Load Json From File ${CURDIR}${/}..${/}tests${/}json${/}example_schema.json
98+
Validate Json By Schema ${json_obj_input} ${schema}
99+
100+
TestValidateJsonBySchemaFileFail
101+
[Documentation] Validate JSON by schema file and fail
102+
${new_json} Delete Object From Json ${json_obj_input} $..phoneNumbers
103+
Run Keyword And Expect Error Json does not match the schema: *
104+
... Validate Json By Schema File ${new_json} ${CURDIR}${/}..${/}tests${/}json${/}example_schema.json
105+
106+
TestValidateJsonBySchemaFail
107+
[Documentation] Validate JSON by schema and fail
108+
${schema} Load Json From File ${CURDIR}${/}..${/}tests${/}json${/}example_schema.json
109+
${new_json} Delete Object From Json ${json_obj_input} $..phoneNumbers
110+
Run Keyword And Expect Error Json does not match the schema: *
111+
... Validate Json By Schema ${new_json} ${schema}
112+
113+
TestValidateJsonByInvalidSchemaFile
114+
[Documentation] Validate JSON by invalid schema file
115+
Run Keyword And Expect Error Json schema error: *
116+
... Validate Json By Schema File ${json_obj_input} ${CURDIR}${/}..${/}tests${/}json${/}broken_schema.json
117+
118+
TestValidateJsonByInvalidSchema
119+
[Documentation] Validate JSON by invalid schema
120+
${schema} Load Json From File ${CURDIR}${/}..${/}tests${/}json${/}broken_schema.json
121+
Run Keyword And Expect Error Json schema error: *
122+
... Validate Json By Schema ${json_obj_input} ${schema}

docs/JSONLibrary.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
with open(os.path.join(HERE, "JSONLibrary", "__version__.py"), encoding="utf8") as f:
77
exec(f.read(), version)
88

9-
requirements = ["robotframework>=3.0", "jsonpath-ng>=1.4.3"]
9+
requirements = ["robotframework>=3.0", "jsonpath-ng>=1.4.3", "jsonschema>=2.5.1"]
1010

1111
setup(
1212
name="robotframework-jsonlibrary",

tasks.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ def install(ctx):
5050
@task(install)
5151
def test(ctx):
5252
ctx.run("tox -p")
53-
ctx.run("robot -d tests/__out__/robot acceptance")
5453

5554

5655
@task

tests/json/broken_schema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"$schemas": "https://json-schema.org/draft/2020-12/schema",
3+
"type": "objects"
4+
}

tests/json/example_schema.json

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
"type": "object",
3+
"properties": {
4+
"firstName": {
5+
"type": "string"
6+
},
7+
"lastName": {
8+
"type": "string"
9+
},
10+
"age": {
11+
"type": "integer"
12+
},
13+
"gender": {
14+
"type": "string"
15+
},
16+
"favoriteColor": {
17+
"type": "array",
18+
"items": {
19+
"type": "string"
20+
}
21+
},
22+
"isMarried": {
23+
"type": "boolean"
24+
},
25+
"address": {
26+
"type": "object",
27+
"properties": {
28+
"streetAddress": {
29+
"type": "string"
30+
},
31+
"city": {
32+
"type": "string"
33+
},
34+
"postalCode": {
35+
"type": "string"
36+
}
37+
}
38+
},
39+
"phoneNumbers": {
40+
"type": "array",
41+
"items": {
42+
"type": "object",
43+
"properties": {
44+
"type": {
45+
"type": "string"
46+
},
47+
"number": {
48+
"type": "string"
49+
}
50+
}
51+
}
52+
},
53+
"bankAccounts": {
54+
"type": "array",
55+
"items": {
56+
"type": "object",
57+
"properties": {
58+
"bank": {
59+
"type": "string"
60+
},
61+
"amount": {
62+
"type": "string"
63+
}
64+
}
65+
}
66+
},
67+
"siblings": {
68+
"type": "array"
69+
},
70+
"occupation": {
71+
"type": "null"
72+
}
73+
},
74+
"required":["firstName", "lastName", "age", "gender", "favoriteColor", "isMarried", "address", "phoneNumbers", "bankAccounts"]
75+
}

0 commit comments

Comments
 (0)