How to get JSONPath to return property of parent of matched element - jsonpath

I have a JSONPath expression that is matching the expected node. But I want to return a property of the parent of that node.
Here is the source json:
{
"totalRecords": 2,
"totalRecordsSpecified": true,
"recordList": [
{
"name": "34-34",
"customFieldList": [
{
"value": {
"name": "PANTS",
"internalId": "46",
"typeId": "91"
},
"internalId": "933",
"scriptId": "custrecord_size_range",
"_typeName": "SelectCustomFieldRef"
}
],
"internalId": "343",
"_typeName": "CustomRecord"
},
{
"name": "34-34",
"customFieldList": [
{
"value": {
"name": "JEANS",
"internalId": "44",
"typeId": "91"
},
"internalId": "933",
"scriptId": "custrecord_size_range",
"_typeName": "SelectCustomFieldRef"
}
],
"internalId": "321",
"_typeName": "CustomRecord"
}
]
}
Here is the JSONPath Expression: $.recordList[.customFieldList[?(#.value.name=='JEANS')]]
and it returns the following match:
[
{
"value": {
"name": "JEANS",
"internalId": "44",
"typeId": "91"
},
"internalId": "933",
"scriptId": "custrecord_size_range",
"_typeName": "SelectCustomFieldRef"
}
]
However, what I want to return is the .internalId property of the PARENT element that contains the customFieldList array from which the above element got matched.
Perhaps by way of screenshot:
How do I need to change my JSONPath Expression to return the indicated parent property?

Formulating the correct syntax to get the expected result comes down to the implementation details of the applied JSONPath library. It looks like you are using the JsonPath-Plus library (since you use this specific online tester). JsonPath-Plus allows us to use the ^ parent-node operator to go one level up, i.e. using your path we could do something like this:
$.recordList[.customFieldList[?(#.value.name=='JEANS')]]^^^.internalId
We can formulate a very straight-forward path that works with the Gatling implementation (and probably some other libraries) like this:
$.recordList[?(#.customFieldList[*].value.name=='JEANS')].internalId
I even found a path that works with Goessner's basic JavaScript JsonPath implementation (It's a bit dubious why index 0 yields the correct result; this probably does not work with multiple results and should be treated with caution)
$.recordList[?(#.customFieldList[0].value.name=='JEANS')].internalId
You can test this path here using various JSONPath implementations (you can switch between tabs, then click Go). As you can see, this very much depends on the underlying library your environment or tool is using.

Related

JSON path evaluation inside JSON path expression

I've got this very simple json :
{
"authors": [
{
"id": 1,
"name": "Douglas Adams"
},
{
"id": 2,
"name": "John Doe"
}
],
"books": [
{
"name": "The Hitchhiker's Guide to the Galaxy",
"author_id": 1
}
]
}
I would like to request the name of the author of "The Hitchhiker's Guide to the Galaxy".
I've tried this JSON path but it doesn't work:
$.authors[?(#.id == $.books[?(#.name == "The Hitchhiker's Guide to the Galaxy")].author_id)].name
All online tools I tried indicate a syntax error which seems due to the presence of a JSON path inside my filter.
Could anyone please help me figure out what's wrong and what is the right syntax?
Thanks!
When you running this filter
$.books[?(#.name == "The Hitchhiker's Guide to the Galaxy")].author_id
it returns an array instead of a value:
[
1
]
Syntax error occurs when you pass an array to compare with the value of id:
$.authors[?(#.id == {the array value}].author_id)].name
However, you may not be able to extract the value using JSONPath, depends on the language you are using. See Getting a single value from a JSON object using JSONPath

Can't get the desired properties via JsonPath evaluate method

I have a json schema that marks special properties in need of processing and I want to query those via JsonPath.Evaluate.
Here's a part of the schema to illustrate the issue
{
"type": "object",
"properties": {
"period": {
"description": "The period in which the rule applies",
"type": "object",
"properties": {
"start": {
"type": "string",
"format": "date-time"
},
"end": {
"type": "string",
"format": "date-time"
}
},
"required": [
"start"
],
"x-updateIndicatorProperties": [
"start"
]
},
"productType": {
"type": "string"
},
"x-updateIndicatorProperties": [
"productType"
]
}
}
I want to get the the JsonPath of the "x-updateIndicatorProperties" properties, so that I can then query the actual properties to process.
For this example, the expected result would be
[
"$['properties']['x-updateIndicatorProperties']",
"$['properties']['period']['x-updateIndicatorProperties']"
]
I've been trying for a while to get a JsonPath expression that would query these properties.
Currently I'm just iterating all properties and filter them manually :
"$..*"
I've also tried using :
$..['x-updateIndicatorProperties']
This works. But it returns a lot of duplicates. For the example above, I get 5 results instead of the expected 2. Can be demonstrated here : https://json-everything.net/json-path
Assuming I can't influence the schema itself, only the code that traverses it,
can anybody help with an expression to get the expected results or any other way to achieve the same outcome?
The stack is JsonPath 0.2.0, .net 6 and system.text.json.
This was a bug in the library when parsing paths that use a recursive descent (..) into a quoted-property-name selector (['foo']). So it would happen for any path in the form $..['foo'].
I've fixed the issue and released version 0.2.1.

How do I add rules to pa11y-ci?

I need to customize the ruleset used by pa11y.
For instance let's say I want to follow WCAG2A but want to add some rules from WCAG2AA.
I tried with something like this for configuration in my .pa11yci-file:
{
"defaults": {
"standard": "WCAG2A",
"rules": ["WCAG2AA.Principle1.Guideline1_1.1_1_1.H30.2"],
"hideElements": "",
"ignore": [],
"includeWarnings": true,
"timeout": 5000,
"threshold": 0
},
"urls": [
{
"url": "https://www.ecster.se",
"actions": [
]
}]
}
But I only get this in the console:
Error: Evaluation failed: Error: WCAG2AA.Principle1.Guideline1_1.1_1_1.H30.2 is not a valid WCAG 2.0 rule
at configureHtmlCodeSniffer (<anonymous>:60:13)
at runPa11y (<anonymous>:30:3)
I get my rulenames from here:
https://github.com/pa11y/pa11y/wiki/HTML-CodeSniffer-Rules
Using latest version of pa11y-ci: 2.1.1.
Looking at the Pa11y documentation it looks as though you need to reference rules without the standard.
E.g. Principle1.Guideline1_1.1_1_1.H30.2, not WCAG2AA.Principle1.Guideline1_1.1_1_1.H30.2
Worth noting that that Guideline you've used as an example is already present in both WCAG2A and WCAG2AA. Might be worth trying with one that's only present in AA and above e.g. Principle3.Guideline3_1.3_1_2.H58.1.Lang
You should have a rules property with an array of rules you wish to include.
...
"rules": [ "standard.you.wish.to.include",...],
...

FHIR : adding a custom extension

I would like to add to add a custom extension to my Schedule resource.
In my app, Schedule have visit motives (reasons). I know there's a list of classified appointments / encounter reasons but I would like to use mine.
I have something like this :
{
"resourceType":"Schedule",
"identifier":"logical_id",
"type":"schedule_speciality",
"actor":{
"practioner_id":"identifier",
"practioner_name":"practioner name"
},
"external_id":{
"extension":[
{
"url":"http://api.test.com/fhir/schedule/external_id",
"valueIdentifier":"external_id"
}
]
},
"visit_motives":{
"extension":[
{
"url":"https://api.test.com/fhir/ValueSet/schedule#visit_motives",
"valueString":"vist_motive1"
},
{
"url":"https://api.test.com/fhir/ValueSet/schedule#visit_motives",
"valueString":"vist_motive2"
},
{
"url":"https://api.test.com/fhir/ValueSet/schedule#visit_motives",
"valueString":"vist_motive3"
}
]
},
"practice_id":{
"extension":[
{
"url":"https://api.test.com/fhir/schedule/practice_id",
"valueIdentifier":"practice_id"
}
]
}
}
I'm not sure about this part :
"visit_motives":{
"extension":[
{
"url":"https://api.test.com/fhir/ValueSet/schedule#visit_motives",
"valueString":"vist_motive1"
},
{
"url":"https://api.test.com/fhir/ValueSet/schedule#visit_motives",
"valueString":"vist_motive2"
},
{
"url":"https://api.test.com/fhir/ValueSet/schedule#visit_motives",
"valueString":"vist_motive3"
}
]
}
Is it correct to add an extension this way ? There are always multiple visit motives for a specific schedule so I have to list them.
I also have seen this kind of things :
"visit_motives": {
"coding": [
{
"system": "https://api.test.com/fhir/ValueSet/schedule#visit_motives",
"code": "visit_motive1"
}
]
}
Which one is the correct one or am I wrong ?
There are several issues here:
It seems odd to capture a "reason" on a schedule. A schedule says when a particular clinician or clinic or other resource is available. E.g. "Dr. Smith takes appointments Mon/Wed/Fri from 1pm-4pm". So if you were to capture a reason on the resource, it would reflect "Why does Dr. Smith have a schedule?" Typically reasons are captured for an individual Appointment. That's the resource that reserves a particular slot for a planned visit. And Appointment already has an element for reason where you're free to use your own codes or just send text.
You have extensions to convey identifiers, but Schedule already has an element for identifiers. Why would you use extensions instead of the standard element? Note that you can use the "system" and/or "type" components to differentiate different kinds of identifiers.
You're sending "identifier", "type", "name", etc. as simple strings - but they're complex data types, so you need to communicate the child elements
actor is of type Reference - that means you need to point to the Practitioner resource. You can't send the properties in-line. (If the Practitioner only exists in the context of the Schedule, you could use the "contained" approach which would use an internal reference, but containment doesn't seem to make sense in this use-case.
The URL for your extension contains ValueSet, which isn't correct - extensions are all structure definitions. Also, there shouldn't be a # symbol in the URL.
Your syntax for extensions is incorrect. You can't introduce new properties in FHIR. The property name for all extensions is just "extension". You differentiate by the URL. So your syntax should be:
{
"resourceType":"Schedule",
"id":"logical_id",
"extension": [
{
"url":"https://api.test.com/fhir/StructureDefinition/schedule-visit_motive",
"valueString":"vist_motive1"
},
{
"url":"https://api.test.com/fhir/StructureDefinition/schedule-visit_motive",
"valueString":"vist_motive2"
},
{
"url":"https://api.test.com/fhir/StructureDefinition/schedule-visit_motives",
"valueString":"vist_motive3"
}
],
"identifier": [
{
"system": http://api.test.com/fhir/NamingSystem/external_id",
"value": "external_id"
}
{
"system": http://api.test.com/fhir/NamingSystem/practice_id",
"value": "practice_id"
}
]
"type": {
"coding": {
"system": "http://somewhere.org/fhir/CodeSystem/specialties",
"code": "schedule_speciality"
},
"text": "Some text description of specialty"
},
"actor":{
"reference": "http://myserver.org/fhir/Practitioner/12345"
"display": "Dr. smith"
}
}

Serialized Entities displaying only ID

I'm using JMSSerializer and FOSRestBundle. I have a fairly typical object graph, including some recursion.
What I would like to accomplish is that included objects beyond a certain depth or in general are listed only with their ID, but when serialized directly, with all data.
So, for example:
Users => Groups => Users
when requesting /user/1 the result should be something like
{ "id": 1, "name": "John Doe", "groups": [ { "id": 10 }, { "id": 11 } ] }
While when I request /group/10 it would be:
{ "id": 10, "name": "Groupies", "users": [ { "id": 1 }, { "id": 2 }, { "id": 4 } ] }
With #MaxDeph I can hide the included arrays completely, so I get
{ "id": 1, "name": "John Doe", "groups": [] }
But I would like to include just the IDs so that the REST client can fetch them if it needs them, or consult his cache, or do whatever.
I know I can manually cobble this together using groups, but for consistency reasons I was wondering if I can somehow enable this behaviour in my entire application, maybe even with a reference to maxdepth so I can control where to include IDs and where to include full objects?
For the sake of those finding this:
I found no other solution, but doing this with groups works just fine and gives me the result I was looking for.

Resources