json schema for a map of similar objects - json

I wish to write a json schema to cover this (simplified) example
{
"errorMessage": "",
"nbRunningQueries": 0,
"isError": False,
"result": {
"foo": {"price":10.0, "country":"UK"},
"bar": {"price":100.2, "country":"UK"}
}
}
which can have this pretty trivial root schema
schema = {
"type":"object",
"required":True,
"properties":{
"errorMessage": {"type":"string", "required":True},
"isError": {"type":"boolean", "required":True},
"nbRunningQueries": {"type":"number", "required":True},
"result": {"type":"object","required":True}
}
}
The complication is the results {} element. Unlike a standard pattern where results would be an array of same objects - each with an id field or similar this response models a python dictionary which looks like this:
{
"foo": {},
"bar": {},
...
}
So given that a will be getting a results object of flexible size with no set keys how can I write json schema for this?
I don't control the input sadly or I'd rewrite it to be something like
{
"errorMessage": "",
"nbRunningQueries": 0,
"isError": False,
"result": [
{"id": "foo", "price":10.0, "country": "UK"},
{"id": "bar", "price":100.2, "country":"UK"}
]
}
Any help or links to pertinent examples would be great. Thanks.

With json-schema draft 4, you can use additionalProperties keyword to specify the schema of any new properties that you could receive in your results object.
"result" : {
"type" : "object"
"additionalProperties" : {
"type" : "number"
}
}
If you can restrict the allowed key names, then you may use "patternProperties" keyword and a regular expression to limit the permited key names.
Note that in json-schema draft 4 "required" must be an array which is bounded to the object, not to each property.

Related

Extract attributes from a JSON node using JSON Path (non-array structure / no extra code)

I'm stuck using JSONPath to extract a list of attributes from a JSON Object / Node without using extra code, just using JSON Path.
Here is an example of the JSON Object
{
"MySchema": {
"fields": {
"FieldOne": {
"required": false,
"type": "long",
},
"FieldTwo": {
"required": false,
"type": "string",
},
"FieldThree": {
"required": false,
"type": "string",
}
}
}
This is just an example, for my production use case, the node ´fields´ contains hundreads of sub nodes. And I cannot parse them manually.
Getting the values of each "Field node" is easy by using :
$MySchema.fields..required
$MySchema.fields..type
But what about the JSONPath expression to use to get the following list (the name of each node only :
FieldOne
FieldTwo
FieldThree
I didn't find the answer in previous posts, most of them are related to arrays / lists.
Kind regards,

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

JsonPath filter query syntax

I'm trying to write a JsonPath query that selects a specific object based on a condition, but either the syntax fails me or I fail the syntax.
Given the below Json object, how would I select the "Data" object containing Dirk Gently's details based on the fact that he uses the "Stumble" method?
{
"Investigators": [
{
"Type": "Legend",
"Object": {
"Method": "Investigate",
"Data": {
"Name": "Sherlock",
"Surname": "Holmes"
}
}
},
{
"Type": "Visionary",
"Object": {
"Method": "Stumble",
"Data": {
"Name": "Dirk",
"Surname": "Gently"
}
}
}
],
"Version": 1
}
I know that I can get to the Method-field like this:
$.Investigators..Object.Method
I assumed that something like this would work:
$.Investigators..Object[?(#.Method=="Stumble")].Data
I'm testing this using: https://jsonpath.com/ to evaluate the query - and I can't seem to get it right.
Am I trying to do something that is not achievable or am I just making a stupid mistake?
Go to this jsonpath online sandbox and try this experssion:
$.Investigators..Object[?(#.Method=="Stumble")].Data
using either the Jayway or Gatling implementations, the output will be:
[
{
"Name" : "Dirk",
"Surname" : "Gently"
}
]

How to validate string and number using json schema

I would like to validate a schema based on either its maximum/minimum (number) OR maximumLength/minimumLength (string).
I have a json form:
[
{
"key":"foo",
"title":"Test",
"type":"string"
}
]
and a json schema:
{
"type": "object",
"properties": {
"foo": {
"type": ["number","string"],
"maxLength":2,
"minLength":0,
"minimum":3,
"maximum":10
}
}
}
and a json model:
{
"foo": "bar"
}
Why does this example not work with validation? The model I have is not validated to false. According to this document it is possible to have different types defined in an array, but how can we do validation based on min/max values?
Your schema is correct. The validator you are using doesn't work properly. Here is an alternative that uses anyOf instead.
{
"type": "object",
"properties": {
"foo": {
"anyOf": [
{ "$ref": "#/definitions/boundedNumber" }
{ "$ref": "#/definitions/boundedString" }
]
}
},
"definitions": {
"boundedString": {
"type": "string",
"maxLength": 2,
"minLength": 0
},
"boundedNumber": {
"type": "number",
"minimum": 3,
"maximum": 10
}
}
}
Although it is quite a bit longer, some would argue that this is actually easier to read/maintain because of the separation of the type specific keywords.
Your schema is validating JSON objects ("type":"object"). In addition, if they have a property with key "foo", its value must be either a number between 3 an 10, or a string of maximum length 2.
Valid objects according to your schema:
{"foo":6}
{"foo":"as"}
Invalid objects:
{"foo":60}
{"foo":"asereje"}
If you want to validate arrays you must define your parent object as an array and use items tag to specify the schema for the array items, for instance:
{
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"foo" : {
"type" : ["number", "string"],
"maxLength" : 2,
"minLength" : 0,
"minimum" : 3,
"maximum" : 10
}
}
}
}
The schema above would validate the following JSON array:
[{
"foo" : 6
}, {
"foo" : "as"
}
]
John the issue is the type "type" : ["number", "string"]
Angular Schema Form is generating fields from the combined JSON Schema and the UI Schema (form), when the field type is defined it knows which type to validate against, when there are multiple types it doesn't know which part of the spec to base the form field against, so it falls back to a textbox and does not add the appropriate validation requirements for string alone.
To achieve your desired outcome you would need to tell it which field type you wish to use. There is a bug in the 0.8.x versions where it does not validate based on the type set in the UI schema if it cannot determine the type in the data schema, I believe that is fixed in the latest development branch. If not if there is an issue raised in Git, I would prioritise it.

Jqgrid. How to handle server response before in will be passed to grid

I have a common structure of JSON data that come back from server, it contains some additional info about errors etc. How can I handle this data(check error info) and then pass only required data to grid.
This is JSON data structure:
{
"errorinfo": "foo",
"errormsg": "foo",
"errorCode": "foo"
"**jqgridData**": [
{
"total": "xxx",
"page": "yyy",
"records": "zzz",
"rows" : [
{"id" :"1", "cell" :["cell11", "cell12", "cell13"]},
{"id" :"2", "cell":["cell21", "cell22", "cell23"]},
...
]
}
]
}
So I wand to process this JSON data and pass to grid only "jqgridData"
Thanks for help.
First of all the JSON data has one small error. The string
{ "errorinfo": "foo", "errormsg": "foo", "errorCode": "foo" "jqgridData": [ {
must be changed to
{ "errorinfo": "foo", "errormsg": "foo", "errorCode": "foo", "jqgridData": [ {
(comma between "errorCode": "foo" and "jqgridData" must be inserted). I hope the problem come during posting of the data in the question text only.
To your main question. The jsonReader allows you to read you practically any data. You data should be read with the following jsonReader:
jsonReader: {
root: "jqgridData.0.rows",
page: "jqgridData.0.page",
total: "jqgridData.0.total",
records: "jqgridData.0.records"
}
(where '0' element is needed as the index because of jqgridData is additionally an array).