I have a json schema defining several properties. I've moved 2 of the properties to definitions and I make references to them. I did this because I wanted to group them together and do some testing for these properties in a generic way. This works fine and all the json data is handled as before.
But, I noticed that when I read the json schema file into my javascript file, I only see the last $ref. I don't know what the cause of this is. I'd really need to know all of the properties that are referenced.
Here's an snippet of my json schema (in file schemas/schema1.json):
{
"type": "object",
"properties": {
"$ref": "#/definitions/groupedProperties/property1",
"$ref": "#/definitions/groupedProperties/property2"
},
"definitions": {
"groupedProperties": {
"type": "object",
"properties": {
"property1": {
"type": "string"
},
"property2": {
"type": "string"
}
}
}
}
}
Then I'm reading it into my js file like this (in file test.js):
var schemas = requireDir('./schemas')
for (var prop in schemas['schema1'].properties) {
console.log(prop)
}
When I iterate over the properties in the schema from my js file, all I can see is one $ref. I imagine this is because it thinks the property name is '$ref' and there can be only unique names. Is there a certain way I need to require this file so that the first $ref doesn't get clobbered?
EDIT: My syntax wasn't passing the json schema validators, although I'm not sure why, so instead of struggling with that, I decided to do it a bit differently. All I wanted was a way to group certain properties, so I put the properties back in the main schema, and changed the definition to be just an enum of the property names comprising the group. So now my schema looks like:
{
"type": "object",
"properties": {
"property1": {
"type": "string"
},
"property2": {
"type": "string"
}
},
"definitions": {
"groupedProperties": {
"enum": ["property1", "property2"]
}
}
}
And then in my js file:
var myGroup = (schema.definitions ? schema.definitions.groupedProperties : [])
console.log(myGroup.enum) // [ 'property1', 'property2' ]
In a JSON schema, a $ref keyword is a JSON Pointer to a schema, or a type or property in a schema. A JSON pointer takes the form of A # B in which: A is the relative path from the current schema to a target schema. If A is empty, the reference is to a type or property in the same schema, an in-schema reference.
In JSON, the “keys” must always be strings. Each of these pairs is conventionally referred to as a “property”. In Python, "objects" are analogous to the dict type. An important difference, however, is that while Python dictionaries may use anything hashable as a key, in JSON all the keys must be strings.
Gets or sets a flag indicating whether the value can not equal the number defined by the minimum attribute (Minimum).
A schema can reference another schema using the $ref keyword. The value of $ref is a URI-reference that is resolved against the schema's Base URI. When evaluating a $ref , an implementation uses the resolved identifier to retrieve the referenced schema and applies that schema to the instance.
There are a lot of problems with how you reference your definitions.
###JSON objects can not have duplicate properties
All properties in a JSON or JavaScript object are unique. The second one will overwrite the first. Consider the syntax for accessing a property to understand why. When you read your JSON into a JavaScript object, you could try accessing the $ref
property using schema.properties['$ref']
. If there were two, which one (or both) would you get? JavaScript has no mechanism to distinguish because it is not allowed.
###$ref
must stand alone
When $ref
is used in an object, it must be the only property in that object. All other properties will be ignored. This is just one more reason why having two $ref
s doesn't work.
Any members other than "$ref" in a JSON Reference object SHALL be ignored.
- https://datatracker.ietf.org/doc/html/draft-pbryan-zyp-json-ref-03#section-3
###$ref
should not be used in properties
$ref
should only be used to reference schemas. In this case, the properties
keyword is using $ref
which is an object with schema values. Using $ref
in this way is not explicitly forbidden in the documentation for JSON Schema or JSON Reference, but it is not idiomatic JSON Schema and is consequently not supported by most validators. Even if the validator you are using does support references like this, it should be avoid because it is never necessary and can make the schema confusing and difficult to maintain.
###Your JSON-Pointers are wrong
Your JSON-Pointers do not actually point to the schemas you have defined. The correct pointer would be #/definitions/groupedProperties/properties/property1
.
###Posible Solutions This is what you were trying to do.
{
"type": "object",
"properties": {
"property1": { "$ref": "#/definitions/groupedProperties/properties/property1" },
"property2": { "$ref": "#/definitions/groupedProperties/properties/property2" }
},
"definitions": {
"groupedProperties": {
"type": "object",
"properties": {
"property1": {
"type": "string"
},
"property2": {
"type": "string"
}
}
}
}
}
Here is a cleaner way to include all of your groupedProperties
at once.
{
"type": "object",
"allOf": [
{ "$ref": "#/definitions/groupedProperties" }
],
"definitions": {
"groupedProperties": {
"type": "object",
"properties": {
"property1": {
"type": "string"
},
"property2": {
"type": "string"
}
}
}
}
}
Or, since you are only using it for testing purposes, you can flip it around so the definition references the schema. You can use the definition in your tests without it affecting your schema.
{
"type": "object",
"properties": {
"property1": { "type": "string" },
"property2": { "type": "string" }
},
"definitions": {
"groupedProperties": {
"type": "object",
"properties": {
"property1": { "$ref": "#/properties/property1" },
"property2": { "$ref": "#/properties/property2" }
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With