JSON schema reference another element in the document - json

Is there a way to express reference to another element in the same JSON document using JSON schema? The title might be a bit confusing, but i'm not looking for the "$ref" attribute, which references another type, but I'm curious, if there is a way, to reference another element in the document using a specified field. I know this is possible to enforce using xsd for xml documents, not sure about JSON.
I want to do something like this:
{
"people": [
{ "id": "1", "name": "A" },
{ "id": "2", "name": "B" },
{ "id": "3", "name": "C" }
],
"chosenOne": "1" // I want the schema to enforce a person ID here
}
I have been looking at the schema definition of v4: http://json-schema.org/draft-04/schema but didn't find anything, that looks like what I'm trying to do. Did I just miss it?

What you want is that you describe a reference ($ref) in the object your schema is describing.
kind of like this
{
"people": []
"chosenOne": { $ref: "#1"}
}
(or maybe a pointer if you want the value of the Id (https://json-spec.readthedocs.io/pointer.html)
I know of no direct way to do this but you might be able to use the pattern or oneof properties to force it being the right value. Kind of like this
"properties": {
"chosenOne"
"type": "string",
"oneOf": ["1","2","3"]
]
},
}
Similarly you could force the value of the property to be a reference pattern. That said since there is no reference value type (http://www.tutorialspoint.com/json/json_data_types.htm) only number or string you can't guarantee the meaning of the value. You can just guarantee that if follows some kind of reference pattern.
If you need more than what json schema's can give you you might want to look in odata for example. OData has some extra things so you can describe an entitySet and then define a navigation property to that set.
It does however force you to follow the odata structure so you aren't as free as you would be with a regular json schema.

Related

JSON Schema object properties defined by enum

I'm attempting to reuse an enum in my JSON Schema to define the properties for an object.
I was wondering if the following is correct.
JSON Schema
{
"type": "object",
"propertyNames": {
"enum": ["Foo","Bar"]
},
"patternProperties": {
".*": {
"type": "number"
}
}
}
JSON Data
{
"Foo": 123,
"Bar": 456
}
The reason I ask is that I get inconsistent results from JSON Schema validation libraries. Some indicate the JSON validates, while others indicate the JSON is invalid.
p.s. if anyone is wondering "why" I'm trying to define the properties with an enum, it is because the enum is shared in various parts of my json schema. In some cases it is a constraint on a string, but I need the identical set of possible values both on those string properties and also on the object properties. As an enum I can maintain the set of possible values in one place.
Yes, that's a valid JSON Schema. You could also express it like this:
{
"type": "object",
"propertyNames": {
"enum": ["Foo","Bar"]
},
"additionalProperties": {
"type": "number"
}
}
It says "all property names must conform to this schema: (one of these values listed in the enum); also, all property values must conform to this schema: (must be numeric type)."
What errors do you get from the implementations that report this as invalid? Those implementations have a bug; would you consider reporting it to them?

How to validate number of properties in JSON schema

I am trying to create a schema for a piece of JSON and have slimmed down an example of what I am trying to achieve.
I have the following JSON schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Set name",
"description": "The exmaple schema",
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"additionalProperties": false
}
The following JSON is classed as valid when compared to the schema:
{
"name": "W",
"name": "W"
}
I know that there should be a warning about the two fields having the same name, but is there a way to force the validation to fail if the above is submitted? I want it to only validate when there is only one occurrence of the field 'name'
This is outside of the responsibility of JSON Schema. JSON Schema is built on top of JSON. In JSON, the behavior of duplicate properties in an object is undefined. If you want to get warning about this you should run it through a separate validation step to ensure valid JSON before passing it to a JSON Schema validator.
There is a maxProperties constraint that can limit total number of properties in an object.
Though having data with duplicated properties is a tricky case as many json decoding implementions would ignore duplicate.
So your JSON schema validation lib would not even know duplicate existed.

Is there a way to unify a json schema into a single file?

I'm looking for a way to unify two json schemas into one, by inserting one as a field of the other. That is to say, the schema A would have a property that is defined by the content of schema B.
To clarify,I don't want to reference schema A from schema B. I want to directly insert the content of B in a specific point of A so that I can have a single JSON document, but I figure that just "pasting" the content into the property programatically wouldn't be enough.
JSON Schema is designed so that you can substitute a reference with its entire contents, and the behavior will be the same, with one possible exception if you use relative URI references.
If you have a schema like "A.json":
{
"type": "object",
"properties": {
"b": {"$ref": "B.json"}
}
}
And you have "B.json":
{ "type": "string" }
This can be collapsed into the following:
{
"type": "object",
"properties": {
"b": { "type": "string" }
}
}
There is one case in which the behavior would change, and that's if you use a relative URI reference, and the URI of the document you're substituting into causes that URI Reference to resolve to a full URI differently than it was before. Use a full (absolute) URI in the root of each schema, in these cases.
I dint'get you question but I try to guess (it could be better if you added an example!). So i think that you have two schema like:
{ "schema": "A",
........
}
{"schema": "B",
.......
}
So, you have two chance to unify them:
-manually
-using a programm
Manually it is trivial because you have to do only copy and paste :
{ "schema": "B",
........
"schema_pasted": "A",
.......
}
or you can use some library to work automatically obtaing the same result (for exaple GSON https://github.com/google/gson in Java).

Json Schema, take into account unspecified properties

Is there is any ways to get heads ups about properties which are not described by schema into the standard. For example this schema:
{
"description": "foo and bar",
"type": "object",
"properties": {
"foo": {
"type": "number"
},
"bar": {
"type": "string",
"enum": [
"a",
"b",
"c"
]
}
}
}
Will pass this JSON:
{
"foo": 12345,
"bar": "a",
"baz": 12312
}
Although it has baz property which is not the part of schema.
UPD: As of now I'm using tv4 library.
Option 1: additionalProperties in the schema
If you want to explicitly constrained to the properties listed in a particular properties definition, then you can use additionalProperties: false. This will restrict data to only using properties defined in the nearby properties entry - in this case, "foo" and "bar".
However, use of additionalProperties impacts schema extension. If you (or someone else) extends this schema later (using allOf/$ref), then the data will still be subject to this schema - so will only be allowed to use "foo" and "bar", regardless of definitions elsewhere.
Option 2: banUnknownProperties flag in tv4
If the kind of complete lock-down is not desired, then you can use the banUnknownProperties flag in tv4 (docs). Basically, after validation, any properties that were not accounted-for by any schemas are raised as errors.
It was designed for cases when extra properties (including future variations/extensions) are theoretically allowed in the data format, but you want (for testing/warning purposes) to be alerted when extra properties show up where you're not expecting them.

How can i define a single, unique Key-Valuepair in JsonSchema?

The Schema should allow only the following constellation: {"status":"nok"}.
The Key must always be "status" and the value should allow "ok","nok","inProgress"
No differen or additional objects,... should be allowed
I have tried this:
{
"description": "blabla",
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ok",
"inProgress",
"nok"
],
"required": true,
"additionalItems": false
}
},
"required": true,
"additionalProperties": false
}
This works, but this scheme allows that i can send the same key/value pair twice like {"status":"nok","status":"nok"}
I would be also happy, if it would work without this "object"-container that i'm using, because to reduce overhead.
Maybe someone knows a solution, thanks
There is a more fundamental issue with that input:
{"status":"nok","status":"nok"}
mainly: that input is not valid JSON. RFC 4627, section 2.2, explicitly states that "The names within an object SHOULD be unique". And in your case, they are not.
Which means the JSON parser you use can do whatever it wants to with such an input. Some JSON APIs will grab whatever value they come upon first, other parsers will grab the last value they read, others will even coalesce values -- none of this is illegal as per the RFC.
In essence: given such input, you cannot guarantee what the output of the JSON parser will be; and as such, you cannot guarantee JSON Schema validation of such an input either.