JSON Schema: verifying object's values, without keys - arrays

Not to confuse anybody, I'll start with validating arrays...
Regarding arrays, JSON Schema can check whether elements of an (((...)sub)sub)array conform to a structure:
"type": "array",
"items": {
...
}
When validating objects, I know I can pass certain keys with their corresponding value types, such as:
"type": "object",
"properties": {
// key-value pairs, might also define subschemas
}
But what if I've got an object which I want to use to validate values only (without keys)?
My real-case example is that I'm configuring buttons: there might be edit, delete, add buttons and so on. They all have specific, rigid structure, which I do have JSON schema for. But I don't want to limit myself to ['edit', 'delete', 'add'] only, there might be publish or print in the future. But I know they all will conform to my subschema.
Each button is:
BUTTON = {
"routing": "...",
"params": { ... },
"className": "...",
"i18nLabel": "..."
}
And I've got an object (not an array) of buttons:
{
"edit": BUTTON,
"delete": BUTTON,
...
}
How can I write such JSON schema? Is there any way of combining object with items (I know there are object-properties and array-items relations).

You can use additionalProperties for this. If you set additionalProperties to a schema instead of a boolean, then any properties that aren't explicitly declared using the properties or patternProperties keywords must match the given schema.
{
"type": "object",
"additionalProperties": {
... BUTTON SCHEMA ...
}
}
http://json-schema.org/latest/json-schema-validation.html#anchor64

Related

Replace field with MongoDB aggregate. Why $set, $addFields and $project, doesn't always replace the field?

Passing an object to an existing field in $set or $addFields merges objects rather than replaces them, e.g.
https://mongoplayground.net/p/aXe-rExjCXr
// Collection
[
{
"_id": "123",
"options": {
"size": "Large",
"color": "Red"
}
}
]
// Aggregate
db.collection.aggregate([
{
$set: {
options: {
size: "Small"
}
}
}
]);
// Expect
[
{
"_id": "123",
"options": {
"size": "Small"
}
}
]
// Actual
[
{
"_id": "123",
"options": {
"size": "Small",
"color": "Red" // <-- Not expected?
}
}
]
(It get's even weirder with arrays)
Is it possible to have it behave like non-object values and simply replace the field?
For context, I want to use this in an aggregate update pipeline.
This is the expected behaviour, and as far as i know there is not plan to change, as far as i remembered there was a jira with this, but they closed it, meaning that it will not change i think.
$set/$addFields replace always except
array field and i add document => array with all members that document
document field and i add document => merge documents (this is your case here)
$project replace always except
array field and i add document => array with all members that document
Solutions
You can override this "weird" behaviour especially in case of
arrays, by $unset the old field first for example, and then $set
Based on the jira in the comment bellow, we can also use $literal to avoid this, but when we use $literal we have to be sure that we dont use expressions because they will not be evaluated.
(expressions like path references, variables, operators etc)

Logic Apps - looping through a nested array in JSON

I need to loop through this optional array (it's only the sectional of JSON I have trouble with).
As you can see from the code:
The optional bullseye has an array rings. rings has arrays of expansionCriteria and expansionCriteria may or may not have actions.
How do I iterate and get all type, threshold in expansionCriteria? I also need to access all skillsToRemove under actions, if available.
I am rather new to Logic Apps, so any help is appreciated.
"bullseye": {
"rings": [
{
"expansionCriteria": [
{
"type": "TIMEOUT_SECONDS",
"threshold": 180
}
],
"actions": {
"skillsToRemove": [
{
"name": "Claims Foundation",
"id": "60bd469a-ebab-4958-9ca9-3559636dd67d",
"selfUri": "/api/v2/routing/skills/60bd469a-ebab-4958-9ca9-3559636dd67d"
},
{
"name": "Claims Advanced",
"id": "bdc0d667-8389-4d1d-96e2-341e383476fc",
"selfUri": "/api/v2/routing/skills/bdc0d667-8389-4d1d-96e2-341e383476fc"
},
{
"name": "Claims Intermediate",
"id": "c790eac3-d894-4c00-b2d5-90cd8a69436c",
"selfUri": "/api/v2/routing/skills/c790eac3-d894-4c00-b2d5-90cd8a69436c"
}
]
}
},
{
"expansionCriteria": [
{
"type": "TIMEOUT_SECONDS",
"threshold": 5
}
]
}
]
}
Please let me know if you need more info.
To generate the schema, you can remove the name of the object at the top of the code: "bullseye":
Thank you pramodvalavala-msft for posting your answer in MS Q&A for the similar thread .
" As you are working with a JSON Object instead of an Array, unfortunately there is no built-in function to loop over the keys. There is a feature request to add a method to extract keys from an object for scenarios like this, that you could up vote for it gain more traction.
You can use the inline code action to extract the keys from your object as an array (using Object.keys()). And then you can loop over this array using the foreach loop to extract the object that you need from the main object, which you could then use to create records in dynamics."
For more information you can refer the below links:
. How to loop and extract items from Nested Json Array in Logic Apps .
.Nested ForEach Loop in Workflow. .

Text inside entities in Draft.js

I've been playing with the Entity system in Draft.js. One limitation I see is that entities have to correspond with a range of text in the content they are inserted into. I was hoping I could make a zero-length entity which would have a display based on the data in the entity rather than the text-content in the block. Is this possible?
This is possible when you have a whole block. As you can see in the code example this serialised blockMap contains a block containing no text, but the character list has one entry with an entity attached to it. There is also some discussion going on regarding adding meta-data to a block. see https://github.com/facebook/draft-js/issues/129
"blockMap": {
"80sam": {
"key": "80sam",
"type": "sticker",
"text": "",
"characterList": [
{
"style": [],
"entity": "1"
}
],
"depth": 0
},
},

JSON Schema: Definitions for array items

I am trying to define an array element in a JSON Schema. They array contains items from a type that is already defined in the definitions section of the schema.
I have tried:
"properties": {
"userId": {"$ref": "#/definitions/userId"},
"beacons": {
"type": "array",
"items": { "$ref": "#/definitions/beaconSchema" }
}
}
The userId part is parsed with #/definitions/userId. The list items, however, ignore the #/definitions/beaconSchema and allow any old junk in it.
How can I use a JSON schema definition to parse all items in a JSON array?
The schema fragment you posted is correct. I suggest you look for typos in the $ref path and definitions property name. If you don't find the problem there, try posting more of the schema.

jsonschema: Verifying that an array contains an element, without erroring on other elements

I recently found jsonschema and I've been loving using it, however recently I've come across something that I want to do that I just haven't been able to figure out.
What I want to do is to validate that an array must contain an element that matches a schema, but I don't want to have validation fail on other elements that would be in the list.
Say that I have an array like the following:
arr = [
{"some object": True},
False,
{"AnotherObj": "a string this time"},
"test"
]
I want to be able to do something like "validate that arr contains an object that has a property 'some object' that is a boolean, and error if it doesn't, but don't care about other elements."
I don't want it to validate the other items in the list. I just want to make sure that the list contains an element that matches the schema at least once. I also do not know the order which the elements will arrive in the array.
I've tried this already with a schema like:
{"type": "array",
"items": {
"type": "object",
"properties": {
"tool": {
# A schema here to validate tool
},
"required": ["tool"]
}
}
The problem is that it requires every item in the array to have the property "tool", and not what I actually want.
Any help anyone can give me with this would be much appreciated! I've been stumped on this for a really long time with no forward progress.
Thanks!
I've gotten an answer to this question:
The schema used is (where ... B ... is the schema to require):
{
"type": "array",
"not": {
"items": {
"not": {... B ...}
}
}
}
It basically works out to be something like "Ensure that not (items don't match B)". I'm not 100% clear on why this works the way it does, but it does so I figured I'd share it for posterity.

Resources