JSON-LD context with array of objects - json

I am trying to define a JSON-LD context that includes an array of objects.
Does anyone know, why the output is empty?
{
"#context": {
"testobjects": {
"#id" : "http://example.org/arrayOfObjects",
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"attr1": { "type" : "number", "default" : 1},
"attr2": { "type" : "string", "default" : "foo"}
}
}
}
},
"testobjects": [
{
"attr1": 216,
"attr2": "test"
},
{
"attr1": 329,
"attr2": "test2"
}
]
}
Output:
[
{
"http://example.org/arrayOfObjects": [
{},
{}
]
}
]
See JSON-LD Playground for trying yourself.

Note that data does not go in a context, so having items as a part of the "testobjects" term definition won't do. There is a proposal to allow multi-dimensional arrays to have individual types, that may be taken up in the future.
For the example you've provided to generate anything, both "attr1" and "attr2" would need to be defined as terms at the top-level of the context, not under an existing context definition.

Related

JSON Schema - Allow only specific enum values for a property and reject the rest

Say I have the following JSON that I'd like validated.
[
{
"UpStatus":"Closed"
},
{
"UpStatus":"Open"
}
]
I want the json to pass validation only if there is at least one 'UpStatus' in the array defined to either 'Open' or 'Locked'.
If 'UpStatus' is not found as set to 'Open' or 'Locked' in the array, and is set to something else that is arbitrary say "Closed", I want the validation to fail.
I tinkered around with anyOf and came up with the following schema.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items": [
{
"type": "object",
"properties": {
"UpStatus": {
"type": "string"
}
},
"minItems": 1,
"anyOf": [
{
"properties": {
"UpStatus": {
"const": "Open"
}
},
"required": [
"UpStatus"
]
},
{
"properties": {
"UpStatus": {
"const": "Locked"
}
},
"required": [
"UpStatus"
]
}
]
}
]
}
The above does not work correctly as it allows the following to pass which I thought it should fail to validate.
[
{
"UpStatus": "Closed"
},
{
"UpStatus": "Closed"
}
]
I played with the json schema for a long time and looked at examples and read some docs but could not get it to work. Any help is appreciated. Thank you.
In your schema above, you put the "minItems" keyword inside "items", which does nothing -- it needs to be adjacent to "items". But using "items" also means that all items must match, not just one.
Instead, use "contains":
{
"type: "array",
"contains": {
"type": "object",
"required": ["UpStatus"],
"properties": {
"UpStatus": {
"enum": ["Open","Locked"],
}
}
}
}
Translation: the data must be an array, where at least one element must be an object, which has the property "UpStatus" with value either "Open" or "Locked".
You may want all items in the array to conform to something specific, in which case you use "items" to specify that. The difference between "items" and "contains" is that the "items" schema must match all items, whereas the "contains" schema only has to match one.
HOWEVER, "contains" is not available in the draft 4 version of the spec. Is there any chance you can upgrade? There is a list of implementations in various languages here. Alternatively, you can simulate the "contains" keyword with "not": { "items": { "not": { ... schema ... } } } (courtesy Jason Desrosiers).
addendum: When I evaluate your schema and data, it does not pass, but rather produces these errors, so perhaps your implementation is buggy (or you mispasted something):
{
"errors" : [
{
"error" : "value does not match",
"instanceLocation" : "/0/UpStatus",
"keywordLocation" : "/items/0/anyOf/0/properties/UpStatus/const"
},
{
"error" : "not all properties are valid",
"instanceLocation" : "/0",
"keywordLocation" : "/items/0/anyOf/0/properties"
},
{
"error" : "value does not match",
"instanceLocation" : "/0/UpStatus",
"keywordLocation" : "/items/0/anyOf/1/properties/UpStatus/const"
},
{
"error" : "not all properties are valid",
"instanceLocation" : "/0",
"keywordLocation" : "/items/0/anyOf/1/properties"
},
{
"error" : "no subschemas are valid",
"instanceLocation" : "/0",
"keywordLocation" : "/items/0/anyOf"
},
{
"error" : "not all items are valid",
"instanceLocation" : "",
"keywordLocation" : "/items"
}
],
"valid" : false
}

Mongodb query on triple nested array of object

I'm having some problem to write a query to return a triple nested value from a document. The documents I'm using are structured like this
{
"areaname": "name1",
"places": [
{
"placename": "place1",
"objects": [
{
"objname": "obj1",
"tags": [
"tag1",
"tag2"
]
},
{
"objname": "obj2",
"tags": [
"tag6",
"tag7"
]
}
]
},
{
"placename": "place2",
"objects": [
{
"objname": "obj45",
"tags": [
"tag46",
"tag34"
]
},
{
"objname": "obj77",
"tags": [
"tag56",
"tag11"
]
}
]
}
]
}
It is quite simple actually but I can't find a solution to a simple query like:
"return the objname of the object that contains tag1 inside their tag"
So for the give document if I use "tag1" as a parameter it is expected for the query to return "obj1"
It should give me the same result if I use "tag2" as a parameter
Other example: using "tag56" it should return only "obj77"
Right now i have no problem returning the whole document using the dot-notation or top level field such as areaname or others
db.users.find( {"places.objects.tags":"tag1"}, { areaname: 1, _id:0 } )
Is this even possible?
Keeping it simple:
[
{
"$match" : {
"places.objects.tags" : "tag1"
}
},
{
"$unwind" : "$places"
},
{
"$unwind" : "$places.objects"
},
{
"$match" : {
"places.objects.tags" : "tag1"
}
},
{
"$group" : {
"_id" : "$_id",
"obj_names" : {
"$push" : "$places.objects.objname"
}
}
}
],
You should add any other fields you want to keep to the group stage,
this can also be done without the double $unwind stage but i choose this for read-ability.

Equal of xsi:type in JSON Schema

How can I hint the type of embedded objects in JSON Schema, analogous to xsi:type in XML Schema?
Example schema document:
{
"type": "storeRequest",
"properties": {
"txid": {
"description": "Transaction ID to prevent double committing",
"type": "integer"
},
"objects": {
"description": "Objects to store",
"type": "array"
"items": {
"type": "object"
},
"minItems": 1,
"uniqueItems": true
},
},
"required": ["txid", "objects"]
}
This is a request the client sends to the server to store multiple objects in the database. Now how can I recursively validate the content of objects when it can contain more than one type of object. (Plymorphism, really).
There is not an equivalent to xsi:type in JSON-schema AFAIK.
Perhaps the most JSON-schema idiomatic way to hint the existence of types would be the explicit definition of types as schemas and referencing them through $ref:
{
"properties" : {
"wheels" : {
"type" : "array",
"items" : "$ref" : "#/definitions/wheel"
}
}
"definitions" : {
"wheel" : {
"type" : "object"
}
}
}
Another way could be to give a hint through enums :
{
"definitions" : {
"vehicle" : {
"properties" : {
"type" : {
"enum" : ["car", "bike", "plane"]
}
}
},
"plane" : {
"properties" : {
"type" : {
"enum" : "plane"
}
}
"allOf" : ["$ref" : "#/definitions/vehicle"]
}
}
}
Finally you can also add whatever tag you can process to a JSON-schema and follow your conventions.
Be aware that you are not going to find an equivalent translation between typical object oriented programming languages (java, C#) inheritance semantics and JSON-schema.

Nested filter numerical range

I have the following json object:
{
"Title": "Terminator,
"Purchases": [
{"Country": "US", "Site": "iTunes", "Price": 4.99},
{"Country": "FR", "Site": "Google", "Price": 5.99}
]
}
I want to be able to find an object specifying a Country+Site+PriceRange. For example, the above should return True on Country=US&Price<5.00, but should return False on Country=FR&Price<5.00. How would the index and query look to do this? Here is another answer that this is a follow-up question to: Search within array object.
Simply add a Range query to your Bool query logic tree. This will return documents that match US for country and have the Price field with a numeric value less than 5.
{ "query":
{ "nested" : {
"path" : "Purchases",
"score_mode" : "avg",
"query" : {
"bool" : {
"must" : [
{
"match" : {"Purchases.Country" : "US"}
},
{
"range" : "Purchases.Price":
{
"lte": 5
}
}
]
}
}
}
}
}

Different types for additionalProperties field in JSONSchema

I have to validate JSONs that look like:
{
"propertyName1" : "value",
"propertyName2" : ["value1", "value2"],
"propertyName3" : { "operator1" : "value" },
"propertyName4" : { "operator2" : ["value1", "value2"] },
...
}
So the propertyName is an arbitrary key, and operators are defined.
I think I should use a schema like:
{
"id" : "urn:my_arbitrary_json#",
"type" : "object",
"required" : false,
"additionalProperties" : {
"id" : "urn:my_arbitrary_key#",
"type" : "object",
"required" : true,
"properties" : {
"operator1" : { ... },
"operator2" : { ... }
}
}
}
However, this schema lacks definition for propertyName1 and propertyName2 cases. I would like to define an array to validate different types of additionalProperties, but this is not correct according to specification. Is there any way to validate such a JSON?
If a given piece of data can be many different shapes, then you can use oneOf or anyOf. For instance here you could have:
{
"type" : "object",
"additionalProperties" : {
"oneOf": [
{... string ...},
{... array of strings ...},
...
]
}
}
Actually, because the options here are all distinct types, you can simply have multiple entries in type instead:
{
"type" : "object",
"additionalProperties" : {
"type": ["string", "array", "object"],
"items": {"type": "string", ...}, // constraints if it's an array
"properties": {...} // properties if it's an object
}
}