JSON.Net: Schema validates where it shouldn't when using anyOf - json

I'm trying to detect if the user specified a boolean as a string instead of a real boolean.
I'm testing commentsModule/enabled to see if the value is false, once with quotes and once without.
The online validator: http://json-schema-validator.herokuapp.com/ works correctly, and identifies the failure as "instance value (\"false\") not found in enum (possible values: [false])".
However, NewtonSoft Json (latest version) with exactly the same schema and json defines this as a valid json.
Schema:
{
"$schema":"http://json-schema.org/draft-04/schema#",
"description": "pages json",
"type": "object",
"properties":
{
"name": {"type":"string"},
"description": {"type":"string"},
"channel": {"type":"string"},
"commentsModule":{
"type": "object",
"anyOf":[
{ "$ref": "#/definitions/commentsModuleDisabled" }
]
}
},
"definitions":{
"commentsModuleDisabled":{
"required": [ "enabled" ],
"properties": {
"enabled": { "type": "boolean", "enum": [ false ] }
}
}
}
}
(using oneOf gives the same result)
JSON:
{
"_id": {
"$oid": "530dfec1e4b0ee95f0f3ce11"
},
"pageId": 1234,
"pageType": "Show",
"name": "my name",
"description": "this is decription.” ",
"channel": "tech",
"commentsModule": {
"CaptionFieldDoesntExist": "Comments",
"enabled": "false"
},
"localInstance": "com",
"productionYear": "2014",
"navbarCaptionLink": "",
"logoAd": ""
}
Json.Net code (taken from the official site):
JsonSchema schema = JsonSchema.Parse(schemaJson);
JObject jsonToVerify = JObject.Parse(json);
IList<string> messages;
bool valid = jsonToVerify.IsValid(schema, out messages);
Thank you!
EDIT:
Json.Net doesn't support Json Schema v4, so the "definitions" references are ignored.
For example, in this case the "caption" is checked for minimal length of 1, and has 0, but Json.net passes validation:
JSON
{
"_id": {
"$oid": "530dfec1e4b0ee95f0f3ce11"
},
"pageId": 1234,
"pageType": "Show",
"name": "another name",
"description": "description ",
"channel": "tech",
"commentsModule": {
"caption": "",
"enabled": true
},
"localInstance": "com",
"productionYear": "2014",
"navbarCaptionLink": "",
"logoAd": "" }
Schema:
{
"$schema":"http://json-schema.org/draft-04/schema#",
"description": "pages json",
"type": "object",
"properties":
{
"name": {"type":"string"},
"description": {"type":"string"},
"channel": {"type":"string"},
"commentsModule":{
"type": "object",
"oneOf":[
{ "$ref": "#/definitions/commentsModuleDisabled" },
{ "$ref": "#/definitions/commentsModuleEnabled" }
]
}
},
"definitions":{
"commentsModuleDisabled":{
"required": [ "enabled" ],
"properties": {
"enabled": { "type": "boolean", "enum": [ false ] }
}
},
"commentsModuleEnabled":{
"required": [ "enabled", "caption" ],
"properties": {
"enabled": { "type": "boolean", "enum": [ true ] },
"caption": { "type": "string", "minLength": 1 }
}
}
} }
the error from the online tool in this case talks about mismatches for both schemas and refers to the minimal length requirement:
"message" : "instance failed to match exactly one schema (matched 0 out of 2)"
... "message" : "string \"\" is too short (length: 0, required minimum: 1)",

Json.Net doesn't support Json Schema v4, only v3. That's why "anyOf" and "definitions" are not recognized and the validation passes.
Update:
Json.NET Schema has full support for Draft 4.

Related

Erroneous successful validation by JSON-schema

The fields in nodes depend on the value of entity. That is, if entity = "pd", then nodes has some fields, while entity = " top " - nodes has completely different fields, despite the fact that they are strictly required. For some reason, the JSON string is accepted by the valid schema, even if there are no fields defined in nodes as required. I already entire head broke, where can be mistake in the most scheme?
JSON-schema:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/root.json",
"type": "object",
"title": "The Root Schema",
"required": [
"virtual"
],
"properties": {
"virtual": {
"$id": "#/properties/virtual",
"type": "array",
"title": "The Virtual Schema",
"items": {
"$id": "#/properties/virtual/items",
"type": "object",
"title": "The Items Schema",
"required": [
"type",
"path",
"entity",
"nodes"
],
"properties": {
"type": {
"$id": "#/properties/virtual/items/properties/type",
"type": "string",
"title": "The Type Schema",
"default": "",
"examples": [
"bus"
],
"pattern": "^(.*)$"
},
"path": {
"$id": "#/properties/virtual/items/properties/path",
"type": "string",
"title": "The Path Schema",
"default": "",
"examples": [
"VBUS2"
],
"pattern": "^(.*)$"
},
"entity": {
"$id": "#/properties/virtual/items/properties/entity",
"type": "string",
"title": "The Entity Schema",
"default": "",
"examples": [
"topaz"
],
"enum": ["pde", "topaz"],
"pattern": "^(.*)$"
},
"nodes": {
"$id": "#/properties/virtual/items/properties/nodes",
"type": "array",
"title": "The Nodes Schema",
"items": {
"$id": "#/properties/virtual/items/properties/nodes/items",
"type": "object",
"title": "The Items Schema"
}
}
}
}
}
},
"anyOf": [
{
"if": {
"properties": { "virtual": { "properties": { "entity": { "const": "topaz" } } } }
},
"then": {
"properties": {
"virtual": {
"properties": {
"nodes": {
"items": {
"required": [
"uid",
"utype",
"uaddress",
"unozzles"
],
"properties": {
"uid": {
"$id": "#/properties/virtual/items/properties/nodes/items/properties/uid",
"type": "integer",
"title": "The Uid Schema",
"default": 0,
"examples": [
1
]
},
"utype": {
"$id": "#/properties/virtual/items/properties/nodes/items/properties/utype",
"type": "string",
"title": "The Utype Schema",
"default": "",
"examples": [
"dispenser"
],
"pattern": "^(.*)$"
},
"uaddress": {
"$id": "#/properties/virtual/items/properties/nodes/items/properties/uaddress",
"type": "string",
"title": "The Uaddress Schema",
"default": "",
"examples": [
"false"
],
"pattern": "^(.*)$"
},
"unozzles": {
"$id": "#/properties/virtual/items/properties/nodes/items/properties/unozzles",
"type": "boolean",
"title": "The Unozzles Schema",
"default": false,
"examples": [
false
]
}
}
}
}
}
}
}
}
},
{
"if": {
"properties": { "virtual": { "properties": { "entity": { "const" : "pde" } } } }
},
"then": {
"properties": {
"virtual": {
"properties": {
"nodes": {
"items": {
"required": [
"id",
"type",
"address",
"nozzles"
],
"properties": {
"id": {
"$id": "#/properties/virtual/items/properties/nodes/items/properties/id",
"type": "string",
"title": "The Id Schema",
"default": "",
"examples": [
"vrt_1"
],
"pattern": "^(.*)$"
},
"type": {
"$id": "#/properties/virtual/items/properties/nodes/items/properties/type",
"type": "string",
"title": "The Type Schema",
"default": "",
"examples": [
"dispenser"
],
"pattern": "^(.*)$"
},
"address": {
"$id": "#/properties/virtual/items/properties/nodes/items/properties/address",
"type": "integer",
"title": "The Address Schema",
"default": 0,
"examples": [
1
]
},
"nozzles": {
"$id": "#/properties/virtual/items/properties/nodes/items/properties/nozzles",
"type": "array",
"title": "The Nozzles Schema",
"items": {
"$id": "#/properties/virtual/items/properties/nodes/items/properties/nozzles/items",
"type": "integer",
"title": "The Items Schema",
"default": 0,
"examples": [
1,
2,
3
]
}
}
}
}
}
}
}
}
}
}
]
}
This JSON is valid:
{
"virtual": [
{
"type": "bus",
"path": "VUS1",
"entity": "pde",
"nodes": [
{
"id": "vrt_1",
"type": "string",
"address": 1,
"nozzles": [1, 2, 3]
},
{
"id": "vrt_2",
"type": "string",
"address": 2,
"nozzles": [1, 2, 3]
}
]
},
{
"type": "bus",
"path": "VUS2",
"entity": "topaz",
"nodes": [
{
"uid": 1,
"utype": "string",
"uaddress": "false",
"unozzles": false
},
{
"uid": "vrt_1",
"utype": "string",
"uaddress": "false",
"unozzles": false
}
]
}
]
}
And this JSON should not be applied, but is considered valid:
{
"virtual": [
{
"type": "bus",
"path": "VUS1",
"entity": "pde",
"nodes": [
{
"id_not_valid": "failure",
"type": 1,
"address": false,
"nozzles": [1, 2, 3]
},
{
"id": "vrt_2",
"type": "string",
"address": false,
"nozzles": [1, 2, 3]
}
]
},
{
"type": "bus",
"path": "VUS2",
"entity": "topaz",
"nodes": [
{
"uid_not_valid": "failure",
"utype": 1,
"uaddress": "false",
"unozzles": false
}
]
}
]
}
In theory, the second JSON should not be validated. For several reasons:
For entity= "pd", the required fields are "id", "type"," address "and"nozzles". In the second line of JSON instead the field "id" is replaced by the field "id_not_valid" - > the obligatory field " id " is absent and validation has to end in failure. The same for entity="top" - "the uid" is replaced by "id_not_valid"
For entity= "pd", the address field is of type token, in the second JSON line it is set to false, which corresponds to the type "boolean", but validation still takes place (the same if you assign an array or string value to address). For entity="top" type, the type is string, but the integer value 1 assigned to it is also assumed by the validator to be the correct string.
But the online validators on the links below say that everything is OK and both JSON conform to the scheme.
The first site
Second site
The third website
So I believe there is an error in the scheme.
The scheme itself was made by this example Example of JSON schema compilation
Any comments and tips on fixing JSON-schema, please
The schema is malformed.
(I'm ignoring the fact that the schema states entity should be "pde" or "topaz", but the instances have "pd" and "top". I assume this is a typo.)
Inside the anyOf, you have two items, each with an if conditional keyword. The schema presented by this keyword is
{
"properties": {
"virtual": {
"properties": {
"entity": {
"const": "topaz"
}
}
}
}
}
This is saying that if virtual has an entity property, then it should be "topaz". But the way that properties works is that it only fails validation if the instance is an object. However in #/properties, you declare that virtual should be an an array of objects where each item contains an entity property.
Since virtual is an array in your instance, none of the if condition keywords in the anyOf pass, so they defer to the else keywords for those subschemas, which don't exist (so the pass by default). This results in both subschemas for the anyOf passing.
I think what you're trying to do is validate each of the items inside the array based on the value of the entity property for that item. This means that you could have both a pde item and a topaz item in the array.
To do this you need to isolate where the variance is. In your case, it's the item level inside the virtual array. This is where you need to put your anyOf.
So you'll want to add your anyOf to #/properties/virtual/items. This is the only point in the schema where an if/then construct can key off of the entity property and enforce the nodes property.
Edit Things I would change
Remove all of the internal $id declarations. They only reiterate the location in the document and provide no additional functionality.
Remove the type and pattern declarations from entity. enum is sufficient here because it declares that the values must be one of the items in the array. Since these are both strings and match the given pattern, those keywords are redundant.
Move the anyOf alongside the properties keyword inside virtual and change it to a oneOf. This is the most specific location where you can access both the entities property and the nodes property. Changing it to a oneOf ensures that exactly one can be true.
Drop the if/then construct and just include the constant value in the then portion.
In the end, it would be structured something like this:
{
... ,
"properties": {
"virtual": {
"type": "array",
"title": "The Virtual Schema",
"items": {
"type": "object",
"title": "The Items Schema",
"required": [ "type", "path", "entity", "nodes" ],
"properties": {
"type": { ... },
"path": { ... },
"entity": {
"title": "The Entity Schema",
"default": "",
"examples": [
"topaz"
],
"enum": ["pde", "topaz"]
}
},
"oneOf": [
{
"properties": {
"entity": {"const": "topaz"},
"nodes": { ... }
}
},
{
"properties": {
"entity": {"const": "pde"},
"nodes": { ... }
}
}
]
}
}
}
}
Here, we're declaring that the items within the virtual array must be objects requiring 4 properties: type, path, entity, and nodes. We explicitly define type, path, entity using the properties keyword. But we conditionally define the nodes property using the oneOf and specifying a constant value for the entity property in each case.

Can't understand this JSON schema from the Swish QR Code API

I'm trying to use an API but the documentation is really bad. I got this JSON schema but I don't understand it. What am I supposed to include in the request?
url: https://mpc.getswish.net/qrg-swish/api/v1/prefilled
I have tried this but it doesn't work:
{
"payee":{
"editable":{
"editable":"false"
},
"swishString":{
"value":"0721876507"
}
},
"size":600,
"border":20,
"transparent":false,
"format":"png"
}
Here's the JSON schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Swish pre-filled qr code generator",
"description": "REST interface to get a QR code that the Swish app will interpret as a pre filled code",
"definitions": {
"editable": {
"description ": "Controls if user can modify this value in Swish app or not",
"type": "object",
"properties": {
"editable": {
"type": "boolean",
"default": false
}
}
},
"swishString": {
"type": "object",
"properties": {
"value": {
"type": "string",
"maxLength": 70
}
},
"required": [
"value"
]
},
"swishNumber": {
"type": "object",
"properties": {
"value": {
"type": "number"
}
},
"required": [
"value"
]
}
},
"type": "object",
"properties": {
"format": {
"enum": [
"jpg",
"png",
"svg"
]
},
"payee": {
"description": "Payment receiver",
"allOf": [
{
"$ref": "#/definitions/editable"
},
{
"$ref": "#/definitions/swishString"
}
]
},
"amount": {
"description": "Payment amount",
"allOf": [
{
"$ref": "#/definitions/editable"
},
{
"$ref": "#/definitions/swishNumber"
}
]
},
"message": {
"description": "Message for payment",
"allOf": [
{
"$ref": "#/definitions/editable"
},
{
"$ref": "#/definitions/swishString"
}
]
},
"size": {
"description": "Size of the QR code. The code is a square, so width and height are the same. Not required is the format is svg",
"value": "number",
"minimum": 300
},
"border": {
"description": "Width of the border.",
"type": "number"
},
"transparent": {
"description": "Select background color to be transparent. Do not work with jpg format.",
"type": "boolean"
}
},
"required": [
"format"
],
"anyOf": [
{
"required": [
"payee"
]
},
{
"required": [
"amount"
]
},
{
"required": [
"message"
]
}
],
"additionalProperties": false,
"maxProperties": 5
}
The API should return a QR code.
To be honest, I have not taken the time to learn JSON schema, but your example should probably look something like this:
{
"payee": {
"value": "0721876507",
"editable": false
},
"size": 600,
"border": 20,
"transparent": false,
"format": "png"
}
There are other parameters you may choose to utilize:
{
"payee": {
"value": "1239006032",
"editable": false
},
"message": {
"value": "LIV",
"editable": true
},
"amount": {
"value": 100,
"editable": true
},
"format": "png",
"size": 300,
"border": 0,
"transparent": true
}
Honestly, I think the developers behind the Swish APIs are trying to look smart by complicating things. They should, of course, have provided example JSON data instead of forcing consumers to understand their JSON schema. Also, I believe their published schema is wrong. The second example I provided works even though it doesn't validate according to the JSON schema ("Object property count 7 exceeds maximum count of 5").
Here is a minimal and pretty useless request that returns a valid QR-code
{
"format": "png",
"size": 300
}
And here is a more usable example that works
{
"format": "png",
"size": 300,
"transparent": false,
"amount": {
"value": 999.99,
"editable": true
},
"payee": {
"value": "0701000000",
"editable": false
},
"message": {
"value": "Hello",
"editable": false
}
}

JSON-Schema oneOf for option under root area

I am trying to get the "oneof" to allow for options in root items but can't find an example and what I try gives an error.
I can get it to work if it is under another item but not under the root {'s
Example - a Job Payment that has required fields (jobNum, payee, amount, type, ) and an option for the payment type (checkInfo or dollarAmt). I know this could be done other ways, but I need this method for a more complex schema.
{
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfo": {
"number": "386"
}
}
{
"JobNum": "x216",
"Payee": "John Doe",
"type" : "Cash",
"amount" : "112.25",
"cashInfo" : {
"dollarAmt" : "112",
"coinAmt" : "0.25"
}
}
The following gives me this error - "Unexpected token encountered when reading value for 'oneOf'. Expected StartObject, Boolean, got StartArray"
{
"description": "Job Payment",
"type": "object",
"required": [ "jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": {
"type": "string"
},
"payee": {
"type": "string"
},
"amount": {
"type": "string"
},
"type": {"enum": [ "check", "cash" ]
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
]
},
"definitions": {
"ptCash": {
"properties": {
"checkInfo": {
"number": "string"
}
},
"required": [ "checkInfo" ],
"additionalProperties": false
},
"ptCheck": {
"properties": {
"dollarAmt": {
"type": "string"
},
"coinAmt": {
"type": "string"
}
},
"required": [ "dollarAmt", "coinAmt" ],
"additionalProperties": false
}
},
"additionalProperties": false
}
There are a a few issues with your schema. I fixed it for you below. I won't explain all the changes I made because I think it is mostly pretty clear by reading the schema. If you want more detail on anything, just ask and I'll update the answer with more details.
The oneOf keyword can only appear in a schema. The properties keyword is an object whose values are schemas. When you put "oneOf" directly under properties, it's not interpreted as a keyword, it's interpreted as a property called "oneOf". The validator then complains because the value of property "oneOf" is expected to be a schema, not an array of schemas like the oneOf keyword.
Your use of additionalProperties doesn't work. This keyword doesn't work the way people often assume that it does. JSON Schema keywords are not aware of any state outside of the schema they are in. Let's look at the "ptCheck" branch of your oneOf first. This describes the property "number", says it is required and that there may be no keywords other than "number". Then your top level defines a the properties "jobNum", "payee", "amount", and "type", requires them all and allows no other properties. These two things can never be true at the same time. Even though your schema is valid, there is no JSON value that can ever be valid against this schema. That's why I moved the definitions of "checkInfo" and "cashInfo" to the top level and only put the required part in oneOf. The only downside to this approach is that you can pass both a "checkInfo" and a "cachInfo" object and it will validate. The extraneous property gets ignored. There are ways around this, but they are problematic enough that I don't advise using them.
I always advise people not to use "additionalProperties": false and to ignore unknown properties instead. The reason is that JSON Schema is a constraint system. Any valid JSON is valid against the empty schema ({}) and each keyword in the schema adds some constraint. This is a different approach to what people are used to when defining classes. An empty class describes nothing and valid values are added. We use "additionalProperties": false to get JSON Schema to behave more like defining a class, but trying to get JSON Schema to behave like something it isn't causes challenges like the one you see here.
{
"description": "Job Payment",
"type": "object",
"required": ["jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": { "type": "string" },
"payee": { "type": "string" },
"amount": { "type": "string" },
"type": { "enum": ["check", "cash"] },
"checkInfo": {
"type": "object",
"properties": {
"number": { "type": "string" }
},
"required": ["number"]
},
"cashInfo": {
"type": "object",
"properties": {
"dollarAmt": { "type": "string" },
"coinAmt": { "type": "string" }
},
"required": ["dollarAmt", "coinAmt"]
}
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
],
"definitions": {
"ptCheck": {
"type": "object",
"properties": {
"type": { "enum": ["check"] }
},
"required": ["checkInfo"]
},
"ptCash": {
"type": "object",
"properties": {
"type": { "enum": ["cash"] }
},
"required": ["cashInfo"]
}
},
"additionalProperties": false
}
oneOf should be placed in prope
Have to re-write rule for both ptCash and ptCheck by using type: object
Following schema should work with ptCheck:
{
"description": "Job Payment",
"type": "object",
"required": [ "jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": {
"type": "string"
},
"payee": {
"type": "string"
},
"amount": {
"type": "string"
},
"type": {"enum": [ "check", "cash" ]
}
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
],
"definitions": {
"ptCash": {
"properties": {
"checkInfo": {
"type": "object",
"required": ["number"],
"properties": {
"number": {
"type": "string"
}
}
}
},
"required": [ "checkInfo" ]
},
"ptCheck": {
"properties": {
"cashInfo": {
"type": "object",
"properties": {
"dollarAmt": {
"type": "string"
},
"coinAmt": {
"type": "string"
}
},
"required": ["dollarAmt", "coinAmt"]
}
},
"required": ["cashInfo"]
}
}
}
Provide some example as below:
import jsonschema
import simplejson as json
schema_filename = '47926398.json'
with open(schema_filename, 'r') as f:
schema_data = f.read()
schema = json.loads(schema_data)
# validate with checkInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfo": {
"number": "386"
}
}
jsonschema.validate(json_obj, schema)
# invalidate
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfox": {
"number": "386"
}
}
jsonschema.validate(json_obj, schema)
# validate with cashInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfo": {
"dollarAmt": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)
# invalidate with cashInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfox": {
"dollarAmt": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)
# invalidate with cashInfo.dollarAmtx
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfo": {
"dollarAmtx": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)

avro runtime exception not a map when return in Json format

i have a avro schema for UKRecord, which contain a list of CMRecord(also avro schemaed):
{
"namespace": "com.uhdyi.hi.avro",
"type": "record",
"name": "UKRecord",
"fields": [
{
"name": "coupon",
"type": [
"null",
"string"
],
"default": null
},
{
"name": "cm",
"type": [
"null",
{
"type": "array",
"items": {
"type": "record",
"name": "CmRecord",
"fields": [
{
"name": "id",
"type": "string",
"default": ""
},
{
"name": "name",
"type": "string",
"default": ""
}
]
}
}
],
"default": null
}
]
}
in my java code, i create a UKRecord which has all fields populated correctly, eventually i need to return this object using a json based api, however it complained:
org.apache.avro.AvroRuntimeException: Not a map: {"type":"record","name":"CmRecord","namespace":"com.uhdyi.hi.avro","fields":[{"name":"id","type":"string","default":""},{"name":"name","type":"string","default":""}]}
the java code that write the object to json is :
ObjectWriter writer = ObjectMapper.writer();
if (obj != null) {
response.setHeader(HttpHeaders.Names.CONTENT_TYPE, "application/json; charset=UTF-8");
byte[] bytes = writer.writeValueAsBytes(obj); <-- failed here
...
}
obj is:
{"coupon": "c12345", "cm": [{"id": "1", "name": "name1"}, {"id": "2", "name": "name2"}]}
why do i get this error? please help!
Because you are using unions, Avro is uncertain how to interpret the JSON you are providing. Here's how you can change the JSON so Avro knows it's not null
{
"coupon": { "string": "c12345" },
"cm": { "array": [
{ "id": "1", "name": "name1" },
{ "id": "2", "name": "name2" }
]
}
}
I know, it's really annoying how Avro chose to handle nulls.

How to define JSON schema for object that holds Properties object?

I need to create a JSON schema for object that will include java Properties object as one of its properties.
The nested Properties object will be simply list of key=value. Both key and value are of type string.
I failed to find any docs that describe how to define the schema that includes 2 new types.
shall it be something like:
{
"type": "object",
"name": "MyObj",
"properties": {
"prop1": {
"type": "string",
"description": "prop1",
"required": true
},
"props": {
"type": "array",
"items": {
"type": "object"
"properties": {
"key": {
"type": "string",
"description": "key",
"required": true
},
"value": {
"type": "string",
"description": "the value",
"required": true
}
}
"description": "the value",
"required": true
}
}
}
}
The schema you have written (assuming the commas are fixed) describes data of the form:
{
"prop1": "Some string property goes here",
"props": [
{"key": "foo", "value": "bar"},
{"key": "foo2", "value": "bar2"},
...
]
}
If this is what you wanted, then you are already finished.
However, I do wonder why you are using key/value pairs in an array, when you could use a JSON object with string keys instead. Using the additionalProperties keyword, you could have a schema:
{
"type": "object",
"name": "MyObj",
"properties": {
"prop1": {
"type": "string",
"description": "prop1"
},
"props": {
"type": "object",
"additionalProperties": {
"type": "string",
"description": "string values"
}
}
}
}
This describes a data format like:
{
"prop1": "Some string property goes here",
"props": {
"foo": "bar",
"foo2": "bar2"
}
}
At W3 schools (JSON Syntax) you can read how the array should be defined.
There is no schema like the xsd for xml, however i've found an approach on json-schema.org. If you are able to, i'll advice to youse google-GSON library for JSON. You could Store key Value as "id" : "value" and build only one object, containing all requieed pairs:
{ "lang" : "EN" , "color" : "red" }
Your posted model is incorect, you can check it on jsonlint.com
Here is a working version, i'm not sure if the modell is as expected.
{
"type": "object",
"name": "MyObj",
"properties": [
{
"prop1": {
"type": "string",
"description": "prop1",
"required": true
},
"props": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "key",
"required": true
},
"value": {
"type": "string",
"description": "the value",
"required": true
}
},
"description": "the value",
"required": true
}
}
}
]
}