What do I call the object-hierarchical "path" of JSON attributes / properties / members and what is their standardized name? - json

Consider I have following typed JSON objects:
Parent: {
"field1" : "Value of field1"
"fieldC" : {Child}
}
Child: {
"field2" : "Value of field2"
}
Q: What do I call field1 and field2?
Just Strings?
Q: What to i call the "path" fieldC.field2?
Accessor path?
Field path?
Member hierarcy path?

field1 and field2 are just strings.
[anything, ..., ... ] is just an array, so the elements of an object.
and then you have 0-9 (with decimals, negative, positive or with e), true/false and null, as numeric values, boolean and nullvalue
{Child} is an object. I don't think it's called path (I'd say that's opinion-based). maybe field-path, but it's rather a child-object. the key is a string and the value is an object/array/string/bool/null/numeric or decimal
all the possibilities e.g.:
{
"string": "string-value",
"nulltype": null,
"child_object": {
"boolean": true,
"any_decimal_int": -1.5e3
},
"array_values":[
{
"any_value": true
},
{
"any_value": false
}
]
}
of course you can combine more and have unlimited child-objects and lists :)

jsonapi.org seems to refer field1,fieldC,and field2 as member names, which I find much more descriptive than just 'Strings'.
As mentioned in my comment to first answer, I guess I'll personally be using (hierarchical) property path or just (object) member hierarchy while referring to 'writing open' the object-hierarchical property/attribute/member 'path' such as fieldC.field2. Seems to be alot of room for interpretation in that. : ]

Related

How to merge a dynamically named record with a static one in Dhall?

I'm creating an AWS Step Function definition in Dhall. However, I don't know how to create a common structure they use for Choice states such as the example below:
{
"Not": {
"Variable": "$.type",
"StringEquals": "Private"
},
"Next": "Public"
}
The Not is pretty straightforward using mapKey and mapValue. If I define a basic Comparison:
{ Type =
{ Variable : Text
, StringEquals : Optional Text
}
, default =
{ Variable = "foo"
, StringEquals = None Text
}
}
And the types:
let ComparisonType = < And | Or | Not >
And adding a helper function to render the type as Text for the mapKey:
let renderComparisonType = \(comparisonType : ComparisonType )
-> merge
{ And = "And"
, Or = "Or"
, Not = "Not"
}
comparisonType
Then I can use them in a function to generate the record halfway:
let renderRuleComparisons =
\( comparisonType : ComparisonType ) ->
\( comparisons : List ComparisonOperator.Type ) ->
let keyName = renderComparisonType comparisonType
let compare = [ { mapKey = keyName, mapValue = comparisons } ]
in compare
If I run that using:
let rando = ComparisonOperator::{ Variable = "$.name", StringEquals = Some "Cow" }
let comparisons = renderRuleComparisons ComparisonType.Not [ rando ]
in comparisons
Using dhall-to-json, she'll output the first part:
{
"Not": {
"Variable": "$.name",
"StringEquals": "Cow"
}
}
... but I've been struggling to merge that with "Next": "Sup". I've used all the record merges like /\, //, etc. and it keeps giving me various type errors I don't truly understand yet.
First, I'll include an approach that does not type-check as a starting point to motivate the solution:
let rando = ComparisonOperator::{ Variable = "$.name", StringEquals = Some "Cow" }
let comparisons = renderRuleComparisons ComparisonType.Not [ rando ]
in comparisons # toMap { Next = "Public" }
toMap is a keyword that converts records to key-value lists, and # is the list concatenation operator. The Dhall CheatSheet has a few examples of how to use both of them.
The above solution doesn't work because # cannot merge lists with different element types. The left-hand side of the # operator has this type:
comparisons : List { mapKey : Text, mapValue : Comparison.Type }
... whereas the right-hand side of the # operator has this type:
toMap { Next = "Public" } : List { mapKey : Text, mapValue : Text }
... so the two Lists cannot be merged as-is due to the different types for the mapValue field.
There are two ways to resolve this:
Approach 1: Use a union whenever there is a type conflict
Approach 2: Use a weakly-typed JSON representation that can hold arbitrary values
Approach 1 is the simpler solution for this particular example and Approach 2 is the more general solution that can handle really weird JSON schemas.
For Approach 1, dhall-to-json will automatically strip non-empty union constructors (leaving behind the value they were wrapping) when translating to JSON. This means that you can transform both arguments of the # operator to agree on this common type:
List { mapKey : Text, mapValue : < State : Text | Comparison : Comparison.Type > }
... and then you should be able to concatenate the two lists of key-value pairs and dhall-to-json will render them correctly.
There is a second solution for dealing with weakly-typed JSON schemas that you can learn more about here:
Dhall Manual - How to convert an existing YAML configuration file to Dhall
The basic idea is that all of the JSON/YAML integrations recognize and support a weakly-typed JSON representation that can hold arbitrary JSON data, including dictionaries with keys of different shapes (like in your example). You don't even need to convert the entire the expression to this weakly-typed representation; you only need to use this representation for the subset of your configuration where you run into schema issues.
What this means for your example, is that you would change both arguments to the # operator to have this type:
let Prelude = https://prelude.dhall-lang.org/v12.0.0/package.dhall
in List { mapKey : Text, mapValue : Prelude.JSON.Type }
The documentation for Prelude.JSON.Type also has more details on how to use this type.

MySQL - JSON - return attribute where value equal true

I have something like this in my table "superheroes":
name | attributes
Batman | {"dead": false, "orphan": true, "billionaire": true, "goodboy" : true}
how can I return all attributes that are true?
I know how to retrieve the value of specific attribute such as
select json_extract((SELECT attributes from superheroes where name = 'Batman'),'$.orphan')
this will return true, which is correct. But I need to find all attributes that are true. Is there a way in MySQL?This is just example, but real situation is little bit too much complicated... Thanks in advance.
I think the closest to what you want is JSON_SEARCH()
SELECT JSON_SEARCH(attributes, 'all', 'true')
FROM superheroes
WHERE name = 'Batman';
However, for this to work, the values have to be strings, not booleans, because JSON_SEARCH treats the search string as a LIKE pattern to match against strings, not a JSON value. So the JSON has to be:
{"dead": "false", "orphan": "true", "billionaire": "true", "goodboy" : "true"}
DEMO

Assigning maxItems property in an array in JSON Schema equal to some other property

I have a property called pageCount which is a number, followed by an array of information based on page number. Now, I want to set the maxItems in the array to be equal to the value of the pageCount. Is there a way that can be done? Most of the places I see we actually use a number to define the maxItems, but can we assign it a value of one of the property in the schema itself?
"pageCount": {
"type":"number",
"mininum": 1,
"required":true
},
"pages": {
"type":"array",
"required":true,
"minItems": 1,
"maxItems" : <to be set as the the value of pageCount??>
As of json-schema Draft v04 you can not use a "property value" to restrict minItems. According to the current state of the standard for minItems:
The value of this keyword MUST be an integer. This integer MUST be
greater than, or equal to, 0.
If you have a small number of "minItems" different options, you could write a schema for each one, something like:
"minArrayItems" : {
"type" : "array",
"minItems" : 1
}
And then reference it through $ref:
"allOf" : { {
"$ref" : "#/definitions/minArrayItems"
}
}
This way you get an indirect way to modify values (just need to modify minArrayItems).
Another option is to add a pre-processing step and build the schema dinamically.
The best option depends on your actual context.

MongoDB find().count() - SyntaxError: missing : after property id (shell):1

Have a .json data-supplied collection of tweets..
Looking to count Delete-Requests in Sessions:
db.tweets.find({"delete"}).count()
And this syntax is incorrect because SyntaxError: missing : after property id (shell):1
Have more find() and count() operations to perform, but the error is consistent.
This is what a Delete-Request looks like (where "…" is either a series of letters and/or numbers):
{
"_id" : ObjectId("…"),
"delete" : {
"status" : {
"id" : NumberLong("…"),
"user_id" : …,
"id_str" : "…",
"user_id_str" : "…"
}
}
}
In the find() function you have to pass an object. You missed the key/value, because {"delete"} isn't a valid object.
I think that you want to get the number of documents that have the delete key. For this you have to use $exists operator with true value.
db.tweets.find({ "delete": { $exists: true } }).count();
or directly
db.tweets.count({ "delete": { $exists: true } });
From documentation:
$exists selects the documents that contain the field if is true. If is false, the query only returns the documents that do not contain the field. Documents that contain the field but has the value null are not returned.

JSON in MongoDb: {"1" : "some content"} VS { _1 : "some content"} Any difference?

I am using a dynamic key that is a series of numbers. Because you have to double quote numbers that are keys in JSON, is there any difference between using a dynamic key that is a number turned to a string versus an underscored number that's a string?
Basically, the difference of converting a number to a string versus concatenating it with an underscore (which turns it to a string).
I DOESN'T seem like there is a difference, however, I'd like to ask this question to everyone because sometimes an unexpected difference does turns up.
{ "1" : "some content",
"2" : "some more content"
}
versus
{ _1 : "some content",
_2 : "some more content"
}
Thanks.
Note that it is not JSON that you are sending to MongoDb but javascript objects. The difference here). And for this reason the following expressions are equivalent.
// unquoted key
db.col.insert({ 1: "key 1 unquoted"})
// quoted key
db.col.insert({ "1": "key 1 quoted"})
So back to your question, the only difference is that in one case you have 1 as key, and in the other _1.
But of course, it depends also what drivers you use to write this data to Mongo. They might be guilty if you see any difference between quoting or not-quoting the keys. Testing in the mongo shell, you get the same results.
The above is all true for top level keys. But if you have keys 1, 2, 3 on other levels, things can become tricky, and for this reason I recommend you not to use numbers as keys. The problems come from the Mongo query syntax when handling arrays.
Assume the following document into a collection:
{
"foo": {
"0": "abc"
},
"bar": [ "x", "y", "z"]
}
Both queries below are valid:
db.col.find({ "foo.0": "abc" })
db.col.find({ "bar.0": "x" })
Just the semantics is different:
in the former query you query for the documents containing a foo key which is an object having a key 0 with value abc
in the latter query you ask for the documents containing a bar key which is an array having x on the first position (0)
is interpreted