Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jsonpath as key accessor #90

Closed
olegorsha opened this issue Oct 21, 2019 · 15 comments
Closed

jsonpath as key accessor #90

olegorsha opened this issue Oct 21, 2019 · 15 comments
Labels
support Users asking how to solve a specific issue

Comments

@olegorsha
Copy link

is it possible use jsonpath as key accessor?
somethings like this:

{
  "id" : $content.container[0].component[?(@.componentType==1)].id
}
@larsga larsga added the support Users asking how to solve a specific issue label Oct 21, 2019
@larsga
Copy link
Collaborator

larsga commented Oct 21, 2019

I don't understand what this is meant to do. Can you explain?

@olegorsha
Copy link
Author

input:

{
  "content": {
    "container": [
      {
        "component": [
          {
            "type": 1,
            "data": {
              "title": "title1",
              "content": "content1"
            }
          },
          {
            "type": 2,
            "data": {
              "title": "title2",
              "content": "content2"
            }
          }
        ]
      }
    ]
  }
}

jstl:

{
  "title": $.content.container[0].component[?(@.type==1)].data.title
  "content": $.content.container[0].component[?(@.type==1)].data.content
}

output:

{
  "title": "title1"
  "content": "content1" 
}

$.content.container[*].component[?(@.type==1)].data.title is jsonpath expression

@larsga
Copy link
Collaborator

larsga commented Oct 21, 2019

I'm not sure what you're trying to do, but this gives you the output you want:

{
  "title": .content.container[0].component[0].data.title,
  "content": .content.container[0].component[0].data.content
}

An even simpler solution is .content.container[0].component[0].data

Not sure this is as general as you would like, though

@olegorsha
Copy link
Author

This is a very simplified document structure. Ideally, I would like to create a template for each type of component and use it in JSLT. But for this I should be able to get the JSON object by component type. Is there any other way to find a JSON object based on the value in it?

@larsga
Copy link
Collaborator

larsga commented Oct 21, 2019

Oh. Now I understand what you were doing.

// traverse the component array, keeping only components of type 1
[for (.content.container[0].component) .data if (.type == 1)]

Output of this would be:

[{
  "title": "title1"
  "content": "content1" 
}]

@olegorsha
Copy link
Author

Thank you.

Now I implemented this as a function

def get_component(node, type)
  if (is-array($node))
    [for ($node) .data if (.componentType == $type)]

{
  "id" : get_component(.content.container.container[0].component, 1)
}

but with jsonpath support it would be much easier.

@larsga
Copy link
Collaborator

larsga commented Oct 26, 2019

I agree something like XPath predicates would be good here. I've thought about this a few times. One way to do it would be to simply say that if the expression in square brackets produces boolean values then it's not array indexing, but instead a filter. With that rule you could write this as:

.content.container.container[0].component[ .type == 1 ].data

I'm not sure whether I like the ambiguity here, so it may be better to have a syntax that explicitly indicates what's going on.

@catull
Copy link

catull commented Oct 26, 2019

You could always use different characters.

Curly braches: .content.container.container[0].component{ .type == 1}.data
Parentheses: .content.container.container[0].component( .type == 1 ).data
Angle brackets: .content.container.container[0].component<.type == 1>.data
Question marks: .content.container.container[0].component?.type == 1?.data
Hashes: .content.container.container[0].component#.type == 1#.data

Your choice.

@larsga
Copy link
Collaborator

larsga commented Oct 26, 2019

Yes. I've considered this:

.content.container.container[0].component[? .type == 1 ].data

.content.container.container[0].component ?[ .type == 1 ].data

.content.container.container[0].component[[ .type == 1 ]].data

Reactions welcome.

@catull
Copy link

catull commented Oct 26, 2019

I prefer the first option.

Reasoning:

  • The question mark is a good symbolic indicator of a boolean evaluation ("Is it true or false")
  • The second choice "ties" the question mark to component, kind of existential. ("Is there an attribute named component, yes or no ?)
  • The third option is too generic, it denotes a calculation, similar to expressions in shell scripts. It just so happens to evaluate to a boolean. It could be used for a dynamic calculation, though.

However, I also like the curly braces I mentioned.
But, out of consistency that indexing and evaluation happen to be in square brackets, I vote for your first option, hanving an expression that produces true/false coated in-between [? and ].

@larsga
Copy link
Collaborator

larsga commented Oct 26, 2019

Yeah, I think I agree.

@catull
Copy link

catull commented Oct 26, 2019

What happens if the expression does not evaluate to true/false, is it automatically false ?

E.g. .content.container.container[0].component[? .type + 1 ].data
where .type is 2.

It would be an error in my world.

@larsga
Copy link
Collaborator

larsga commented Oct 26, 2019

We have automatic conversion to boolean other places in the language. if (1) 2 evaluates to 2. So we should probably do the same here, since the user has explicitly stated this is a boolean filter.

One nice thing about that is that existence checks become very natural. Get me all the sub-objects which have the field bar:

.foo[? .bar ]

@catull
Copy link

catull commented Oct 26, 2019

Great.

The original question was, do you plan to support JSON path expressions, not just conditional expressions ?

He asked for "jsonpath as key accessor", and gave a conditional example.
I believe we have addressed the conditional aspect.

I am happy with that.

I just noticed this is a theoretical question.
You only add functionality if there is an actual need, which there isn't here.

@larsga
Copy link
Collaborator

larsga commented Oct 26, 2019

Well, I didn't understand the initial question, and I still don't, so I can't really answer it. What "JSON path expressions" are being asked for that the language doesn't have?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
support Users asking how to solve a specific issue
Projects
None yet
Development

No branches or pull requests

3 participants