0

On the below JSON example, I need to get only 1 ID when 'contenttype'!='helptext'

I cannot do 'contenttype'=='textAreaSelectionLong' because a lot of other types are possible.

Since it's on a different node on the same level as id, I don't know how to write it in a single JSON path expression.

I tried the below JSON path,

$.children[?(@.name=='p')].children[?(@.name=='@id')].text

And it gives me,

[
  "id2",
  "id3"
]

But I am expecting a JSON path that could return only id2

Below is a chunk of JSON that this example is based on,

{
    "children": [
        {
            "name": "@id",
            "text": "id1",
            "children": []
        },
        {
            "name": "contenttype",
            "text": "question",
            "children": []
        },
        {
            "name": "p",
            "text": "Some random text 1",
            "children": [
                {
                    "name": "contenttype",
                    "text": "textAreaSelectionLong",
                    "children": []
                },
                {
                    "name": "@id",
                    "text": "id2",
                    "children": []
                }
            ]
        },
        {
            "name": "p",
            "text": "Some random text 2",
            "children": [
                {
                    "name": "@id",
                    "text": "id3",
                    "children": []
                },
                {
                    "name": "contenttype",
                    "text": "helptext",
                    "children": []
                }
            ]
        }
    ]
}

Could anyone tell me if the below JSON path makes sense. Just an update to the above JSON path?

$.children[?(@.name=='p' && @.children[?(@.name=='contenttype')].text!='helptext')].children[?(@.name=='@id')].text

Apparantly, jsonpath.com doesn't seem to properly parse this and give me the expected result. I know that it logically makes sense. But, is the syntax fine?

Giftson David
  • 23
  • 1
  • 9
  • Did this one work? `$..[?(@.text== 'Some text 1')]..[?(@.name=='@id')].text` – lucas-nguyen-17 Nov 03 '21 at 11:54
  • Unfortunately no. The `Some text 1` is also random. So, I cannot tie that up to the condition as well. Only object that could be used in a condition is `name` – Giftson David Nov 03 '21 at 12:06
  • @lucasnguyen17 `helptext` is one of the values I want to avoid while fetching the data. So, only to do that, we may use something like `[?(@.text != 'helptext')]`. Let me know if you have any other suggestions – Giftson David Nov 04 '21 at 07:53
  • You can get all `text` by JsonPath then remove 'helptext' after that. I have no idea to achieve the goal with only JsonPath. – lucas-nguyen-17 Nov 04 '21 at 10:02
  • @lucasnguyen17 Thanks for the suggestion. However, I would really need to achieve this using JSON path as I have a constraint to use Azure Data Factory for ETL. It is configured to map based on JSON paths only. – Giftson David Nov 04 '21 at 17:22
  • Use [Jayway JsonPath Evaluator](https://jsonpath.herokuapp.com/) to test online if you are using java port of jsonpath. – Akshay G Nov 18 '21 at 07:40

1 Answers1

1

If you are using Jayway JsonPath java port you can use the Filter Operator nin

JSONPath

$.children[?('helptext' nin @.children[*].text)].children[?(@.name=='@id')].text

Online Test Tool : Jayway JsonPath Evaluator

enter image description here

Akshay G
  • 2,070
  • 1
  • 15
  • 33
  • Thanks. Your expressions assume that it's available on a fixed node position. It's however not possible in the JSON that I receive. Anyway, leaving this question open to see if someone is able to suggest an answer or approach. – Giftson David Nov 19 '21 at 08:51
  • @GiftsonDavid if you are using java port (Jayway jsonpath), check my updated answer. It should work – Akshay G Nov 19 '21 at 10:35
  • Thanks Akshay for the updated answer. It serves my purpose. I've accepted it too. – Giftson David Nov 19 '21 at 12:20