How to filter a non-array in JsonPath - json.net

Using the following JSON (from http://jsonpath.com):
{
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
},
"phoneNumbers": [
{
"type" : "iPhone",
"number": "0123-4567-8888"
},
{
"type" : "home",
"number": "0123-4567-8910"
}
]
}
I would like to get the root object only if firstName is John.
I have tried these inputs and many other similar ones:
$.[?($.firstName == 'John')]
$.[?($.'firstName' == 'John')]
$.[?(#.firstName == 'John')]
$[?($.firstName == "John")]
It seems as though filtering is only intended for arrays so this is an unsupported function. Does someone know a way to do this in Json.NET, or confirm that it's not possible and maybe point me to a library which supports the above?
I'm using F# but that's not important because F# is compatible with C#, .NET and NuGet packages.

JSON path is intended to locate data in a JSON object and not to perform some processing or testing on that data. The filter notation is used to identify an item in an array with the purpose of returning that data or some part of it. Having objects in an array means that there may be many properties with the same name that have to be filtered by some other means in order to select a subset of them.
Using filter notation on an object property is not the same thing. There can only be one property in an object with a particular name so stating that name is sufficient to identify it uniquely. You can easily achieve the effect you require by getting $.firstName and then testing separately for the value "John"

Related

How to filter an array of objects using multiple conditions in JSONPATH?

I am using jsonpath library (https://github.com/json-path/JsonPath) in Go, and I need to process a JSON object and filter from an array of objects, the objects which match any of the multiple criteria (OR conditions). I have been unsuccessful in getting the filter to work correctly and hoping that someone can help me in the right direction. I am providing a simplified example below.
Let us assume I have the following JSON Object.
{
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
},
"phoneNumbers": [
{
"type" : "iPhone",
"number": "123-4567-8888"
},
{
"type" : "home",
"number": "123-4567-8910"
},
{
"type" : "mobile",
"number": "123-4567-1233"
}
]
}
I would like filter all phone numbers (phoneNumbers) which are of type "home" or "iPhone". I have used the following expression, but it results in an empty array:
$.phoneNumbers[?(#.type=='home' || #.type == 'iPhone')]
Please see this JSONPath expression tester below. I have saved the JSON here, but it doesn't keep the JSONPath expression, and it will need to be pasted manually.
JSONPath Expression Tester

Pact: How do I match an object whose keys match a regular expression?

I am trying to write a pact consumer test to match the following response.
[
{
"accountId" : 1,
"permissions" : [
{
"schedule" : {
"01/01/2018" : false,
"01/01/1900" : true
},
"permissionId" : 3
}
]
}
]
Each schedule object is composed of an unknown number of keys which match a simple regular expression. But I don't see a way to match a key using a regular expression while having the value map to a simple boolean.
For instance, I see the following method in the API.
public LambdaDslObject eachKeyLike(
String exampleKey,
Consumer<LambdaDslObject> nestedObject)
But that is going to expect a new object as the value, instead of a primitive type.
"schedule" : {
"01/01/2018" : { ... }, // not what I want to match
"01/01/1900" : false // what I want to match
}
Is there a way to specify an imprecise key mapped to a primitive value in pact-jvm?
Sorry, this feature doesn't exist yet, but it's been discussed for the next version of the pact specification. You can add your thoughts on this issue: https://github.com/pact-foundation/pact-specification/issues/47

Nested arrays are not supported

The new Firebase database Firestore says
Function DocumentReference.set() called with invalid data. Nested arrays are not supported.
When trying to save the following object:
{
"desc" : "Blala",
"geojson" : {
"features" : [ {
"geometry" : {
"coordinates" : [ 8.177433013916017, 48.27753810094064 ],
"type" : "Point"
},
"type" : "Feature"
} ],
"type" : "FeatureCollection"
},
"location" : {
"lat" : 48.27753810094064,
"lng" : 8.177433013916017
},
"name" : "Wald und Wiesen",
"owner" : "8a2QQeTG2zRawZJA3tr1oyOAOSF3",
"prices" : {
"game" : {
"Damwild" : 10,
"Raubwild" : 300,
"Rehwild" : 250,
"Schwarzwild" : 40
},
"perDay" : 35
},
"rules" : "Keine Regeln!",
"wild" : {
"desc" : "kein Wild",
"tags" : [ "Damwild", "Rehwild", "Schwarzwild", "Raubwild" ]
}
}
what exactly is the nested array that firestore is complaining about? I can't find it in the documentation.
If it's the GeoJSON object - how would I save it instead?
UPDATE: This was fixed in Firebase JS SDK 4.6.0. Directly nested arrays are still unsupported, but you can now have an array that contains an object that contains an array, etc.
This is a bug in the currently released SDKs.
The backend has the restriction that only directly nested Arrays are unsupported.
In your case you have arrays containing objects containing arrays and the validation logic in the clients is disallowing it when it shouldn't.
There's no public bug tracking this but I'll post back when we have a fix.
You could adapt a serialization function that converts arrays with object types into a map. The keys can be numeric to maintain order.
i.e.
{ 1: Object, 2: Object2 ... }
On deserialization you can get the Object.values(data); to put it back into an array to be used client-side.
Can't comment so here it goes: this is fixed in 4.6.0, see release notes: https://firebase.google.com/support/release-notes/js#4.6.0
Cloud Firestore
FIXED Fixed the validation of nested arrays to allow indirect nesting.
Python:
# Matrix storage in firestore
def matrix_to_fb_data(matrix):
return [{'0': row} for row in matrix]
def fb_data_to_matrix(fb_data):
return [row['0'] for row in fb_data]
Firestore doesn't allow 2d arrays, like previous answers have noted, but they allow arrays of maps... of arrays :)

How to create GTM data layer variable with complex array

In Google Tag Manager a pre-defined variable type of "Data Layer Variable" exists with an input for the variable name. In a standard single level of key/value pairs this is easy.
var dataLayer = [{"mykey":"myvalue"}];
Given that data layer you'd just use mykey as your variable to input into GTM. However, if you use the CEDDL spec (http://www.w3.org/2013/12/ceddl-201312.pdf) structure you end up with a deeply nested array:
dataLayer = [
{
"product": [
{
"category": {
"primaryCategory": "Auto Loans"
},
"productInfo": {
"productID": "1",
"productName": "PurchaseLoan",
"description": "Auto finance loan"
},
"security": [
"Analytics",
"Personalization",
"Recommendations"
]
}
]
}
]
So the real question is: how do I access the value of "productName" in the above example?
In standard Javascript you might access it like so:
dataLayer[1].product[0].productInfo.productName
or
dataLayer.1.product.1.productInfo.productName
... but neither of these options work (with or without dataLayer.1 as the first node).
This is the UI to enter the variable name:
When you define your DataLayer variable in GTM, you don't need to specify "dataLayer" in the variable name, ie. it should just be:
product.0.productInfo.productName

How do you find the PHID of a Phabricator object?

I need to get the PHIDs for one project and several users in our Phabricator install. It seems like it should be trivial to find out how to do this, but I've searched the docs to no avail. Am I looking in the wrong place or something?
Easiest way:
Go to the project
Click New Task
Look at the URL, it will have a parameter like:
?projects=PHID-PROJ-owipizovyry4fatifwfd
PHID is "PHID-PROJ-owipizovyry4fatifwfd"
Option 2:
Go to your Conduit [phabricator_url]\conduit
Find the method project.query
Enter the name in a JSON encoded array (i.e. ["project name"])
Click Call Method
PHID will be one of the data elements:
{
"data" : {
"PHID-PROJ-oybqquyhhke4awiw2akz" : {
"id" : "19",
"phid" : "PHID-PROJ-oybqquyhhke4awiw2akz",
"name" : "project name",
"members" : [
"PHID-USER-gapak5h34h6d5yvl67dx",
"PHID-USER-674vq754zfuhyxgvvq7x",
"PHID-USER-qvcdsyc4oz7rzpzziiyk",
"PHID-USER-qmefzjtsrmnxjxpc45km",
"PHID-USER-pbhygge7rgpdowz3s5vk"
],
"slugs" : [
"project_name"
],
"dateCreated" : "1396666703",
"dateModified" : "1396668261"
}
}
}
A more robust method would be to call the conduit method phid.lookup:
https://<your install>/conduit/method/phid.lookup/
Then enter in names something like #user, #project or Z2 and you'll get the PHID.

Resources