Can json schema references have a template? - json

I'm working on reducing json schema, to try and make it easier to follow. Many of my nodes are of the same general form:
{
"[$PassedName]": {
"type": "object",
"properties": {
"current": {
"type": "object",
"[$PassedName]" : {"$ref": "#/definitions/Objects/[$PassedName]"}
},
"history": {
"type": "array",
"[$PassedName]" : {"$ref": "#/definitions/Objects/[$PassedName]"}
}
}
}
}
What I'd like to do is to pass a string to a reference, so the reference could use that string in the given locations. For example, giving the reference the string value "SSN" would have a resultant schema of the following:
{
"SSN": {
"type": "object",
"properties": {
"current": {
"type": "object",
"SSN": "#/definitions/Objects/SSN"
},
"history": {
"type": "array",
"SSN": "#/definitions/Objects/SSN"
}
}
}
}
Is this at all possible with json schemas? I've more than a dozen of basically the same node, so I'd like to simplify, if possible.

Related

Is it possible to reference to JSON data itself within a schema definition?

Is it possible to define a JSON schema to check inner data integrity? So that mistakes like "ba" could be detected without further runtime checks.
Data JSON
{
"childNames": ["foo", "bar", "baz"],
"children": [
{
"name": "foo"
},
{
"name": "ba"
}
]
}
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://tbd.com/foo/bar",
"type": "object",
"properties": {
"childNames": {
"type": "array",
"items": { "type": "string" }
},
"children": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"enum": { "$ref": "???" }
}
}
}
}
}
}
If you're using .Net, then you can do this with JsonSchema.Net and JsonSchema.Net.Data.
You'll need to use a custom vocabulary which defines the data keyword.
Your schema will need to change to:
{
"$schema": "https://gregsdennis.github.io/json-everything/meta/data",
"$id": "https://tbd.com/foo/bar",
"type": "object",
"properties": {
"childNames": {
"type": "array",
"items": { "type": "string" }
},
"children": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"data": {
"enum": "#/childNames"
}
}
}
}
}
}
}
Note the data keyword where your ??? was and the different meta-schema in the $schema keyword.
You can try it on https://json-everything.net/json-schema.
Information on how this works is here.
If you're not using .Net, you may need to figure out how to support this vocabulary (or work with the maintainer of the library you're using to do so).
Disclaimer: I'm the creator & maintainer of JsonSchema.Net and the other json-everything libraries.

JSON Schema reference resolution

I have a JSON schema that contains "$ref" tags and I am trying to get a version of the JSON schema that have the "$ref" tags resolved. I am only looking to resolve "$ref" from definition (tags) within the JSON Schema string (ie. not external resolution needed).
Is there a library that performs the resolution of the JSON Schema? (I am currently using org.everit.json.schema library, which is great, but I can't find how to do what I need).
For example, my original schema is:
{
"$id": "https://example.com/arrays.schema.json",
"description": "A representation of a person, company, organization, or place",
"title": "complex-schema",
"type": "object",
"properties": {
"fruits": {
"type": "array",
"items": {
"type": "string"
}
},
"vegetables": {
"type": "array",
"items": { "$ref": "#/$defs/veggie" }
}
},
"$defs": {
"veggie": {
"type": "object",
"required": [ "veggieName", "veggieLike" ],
"properties": {
"veggieName": {
"type": "string",
"description": "The name of the vegetable."
},
"veggieLike": {
"type": "boolean",
"description": "Do I like this vegetable?"
}
}
}
}
}
Which would resolve to something like this (notice that the "#defs/veggie" resolves to its definition inserted inline in the schema):
{
"$id": "https://example.com/arrays.schema.json",
"description": "A representation of a person, company, organization, or place",
"title": "complex-schema",
"type": "object",
"properties": {
"fruits": {
"type": "array",
"items": {
"type": "string"
}
},
"vegetables": {
"type": "array",
"items": {
"type": "object",
"required": [ "veggieName", "veggieLike" ],
"properties": {
"veggieName": {
"type": "string",
"description": "The name of the vegetable."
},
"veggieLike": {
"type": "boolean",
"description": "Do I like this vegetable?"
}
}
}
}
}
}
This isn't possible in the general sense, because:
the $ref might be recursive (i.e. reference itself again)
the keywords in the $ref might duplicate some of the keywords in the containing schema, which would cause some logic to be overwritten.
Why do you need to alter the schema in this way? Generally, a JSON Schema implementation will resolve the $refs automatically while evaluating the schema against provided data.

Json schema with keys as data

I have some hard time dealing with json schema.
Suppose this is initial simple json.
[
{
"Field1": 1,
"Description": "Default"
},
{
"Field1": 77,
"Description": "NonDefault"
}
]
And this is schema written which is valid
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {
"type": "object",
"properties": {
"Field1": {
"type": "integer"
},
"Description": {
"type": "string"
}
}
}
}
I wanted to change Json, to use "Field1" as key.
"Field1" is integer value.
I do not know values and how many Field1 there will be in json.
This is final JSON
{
"1": {
"Description": "Default"
},
"77": {
"Description": "NonDefault"
}
}
But how to write json-schema for this JSON?
TimRoberts' answer is almost there. What you want is to describe the item in the patternProperties subschema, similar to how you have items in your example schema.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"patternProperties": {
"^[0-9]*$": {
"type": "object",
"properties": {
"Description": { "type": "string" }
}
}
}
}
You can use "propertyNames" with a "pattern" element to create a regular expression to qualify your key names, instead of enumerating them all. I, personally, prefer your first layout.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"patternProperties": {
"^[0-9]*$": { "type": "string" }
}
}

Json Schema Dependencies with Object Definitions

When using json schema 7 is it possible to set a dependency on an object definition references rather individual fields?
For example I have a type string and properties object. Depending on the type the properties object fields will be different but I don't want to set dependancy of every possible field. That's rather tedious e.g.
{
"$id": "https://sibytes.datagovernor.com/dataset.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "dataset",
"type": "object",
"properties": {
"dataset_type": {
"type": "string",
"description": ""
},
"dataset_properties": {
<< BASICALLY HERE I WANT THE REFERENCE OBJECT DEFINITION TO BE DEPENDENT ON THE DATASET TYPE ABOVE>>
"$ref": "http://example.com/tableproperties.schema.json"
"$ref": "http://example.com/tableproperties.fileproperties.json"
...there will be others.
}
}
}
So turns out this can de done using sub-schema's and predicates
https://json-schema.org/understanding-json-schema/reference/conditionals.html
{
"$id": "https://sibytes.datagovernor.com/dataset.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "dataset",
"type": "object",
"properties": {
"dataset_type": {
"enum": ["Table","View"],
"description": "This is the type of physical object that the dataset describes."
}
},
"dataset_properties": {
"allOf": [
{
"if": {
"properties": {"dataset_type":{"const": "Table"}}
},
"then": {
"properties": {
"dataset_properties" : {
"$ref": "dataset.table.schema.json#/definitions/dataset_properties"
}
}
}
},
{
"if": {
"properties": {"dataset_type":{"const": "View"}}
},
"then": {
"properties": {
"dataset_properties" : {
"$ref": "dataset.view.schema.json#/definitions/dataset_properties"
}
}
}
}
]
},
"required": ["dataset_type","dataset_properties"]
}

Encapsulate Root object by name in Json schema for reuse?

I'm trying to create a Json schema for an object. Is it possible to reference the top level root object, when defining an embedded object within it?
I've seen that I can reuse a definition through $ref:"#/definitions/..." but I am trying to reuse the whole top level object. Not just the properties within.
if my json looks like this:
{
"name": "brodie",
"age": 2,
"bestFriend": {
"name": "clara",
"age": 4,
"bestFriend": {
"name": "stella",
"age" : 5
}
}
}
I can create a json schema that looks like this:
{
"type": "object",
"properties": {
"name": {
"$ref": "#/definitions/name"
},
"age": {
"$ref": "#/definitions/age"
},
"bestFriend": {
"$ref": "#/definitions/bestFriend"
},
},
"definitions": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
},
"bestFriend": {
"type": "object",
"allOf": [
{"$ref": "#/defintions/name"},
{"$ref": "#/definitions/age"},
{"$ref": "#/definitions/bestFriend"}
]
}
}
}
But I'd like to do something like
{
"type": "object",
"title": "bestFriend",
"properties": {
"$ref": "#/definitions/bestFriend"
},
"definitions": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
},
"bestFriend": {
"type": "object",
"allOf": [
{"$ref": "#/defintions/name"},
{"$ref": "#/definitions/age"},
{"$ref": "#/definitions/bestFriend"}
]
}
}
}
I am using the same json object for all 3 instances brodie, clara, stella. I want to encapsulate the top level object as one definition so I can reference it later in a cleaner way. It would be nice if I didn't have the list of $refs at the top and only had them within the "definitions" object at the bottom. Is this even possible? Or is what I have above the recommended pattern.
(I know I could define some of these fields inline, but I plan on heavily reusing some json objects, and felt it would be cleaner if everything was defined in the "definitions" section.)