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

Cannot select field if field name has dashes #38

Closed
ilkka opened this issue Oct 25, 2012 · 26 comments
Closed

Cannot select field if field name has dashes #38

ilkka opened this issue Oct 25, 2012 · 26 comments
Labels

Comments

@ilkka
Copy link

ilkka commented Oct 25, 2012

Given this JSON:

[
    {
        "my-field": "val1",
        "other_field": "valA"
    },
    {
        "my-field": "val2",
        "other_field": "valB"
    }
]

this works:

$ ./jq '[.[]|{other_field}]' < test.json
[
  {
    "other_field": "valA"
  },
  {
    "other_field": "valB"
  }
]

but this does not:

$ ./jq '[.[]|{my-field}]' < test.json
error: syntax error, unexpected '-', expecting '}'
[.[]|{my-field}]
        ^
1 compile error

I think it should since the JSON is valid. Maybe there is a way around this?

@stedolan
Copy link
Contributor

Currently, that gets parsed as a subtraction. You can always explicitly use strings for when your keys don't fit identifier syntax:

{"my-new-field": .["my-old-field"]}

@ilkka
Copy link
Author

ilkka commented Oct 31, 2012

Guess that makes sense, I just didn't stumble across that syntax :)

@ilkka ilkka closed this as completed Oct 31, 2012
stedolan added a commit that referenced this issue Dec 3, 2012
Useful when "foo" contains unusual characters. Should help with
the issues #7, #38, #40, #42.
@woohgit
Copy link

woohgit commented Apr 29, 2013

This means I cannot get a value from a json if the key contains a dash:

< json.json jq .stuff.thisisakey-key.identifier

because it'll throws:

error: key is not defined
.stuff.thisisakey-key.identifier
                  ^^^
1 compile error

How can I do it? I tried with "" and so on, but none of them works.

@ghost
Copy link

ghost commented Apr 29, 2013

jq '.stuff["thisisakey-key"].identifier' http://stedolan.github.io/jq/manual/#foo it's similar in JavaScript

@zasran
Copy link

zasran commented Mar 6, 2014

According to http://stedolan.github.io/jq/manual/ "If the key contains special characters, you need to surround it with double quotes like this: ."foo$"."

However the following does not work:

$ echo '{"a-b":"0"}' | jq '."a-b"'
error: syntax error, unexpected QQSTRING_START, expecting $end
."a-b"
^
1 compile error

This works:

$ echo '{"a-b":"0"}' | jq '.["a-b"]'
"0"

However it's not clear how to make it work if you want to get a nested value:

$ echo '{"a-b":{"c-d":0}}' | jq '.["a-b"]."c-d"'
error: syntax error, unexpected QQSTRING_START, expecting IDENT
.["a-b"]."c-d"
^
1 compile error

$ echo '{"a-b":{"c-d":0}}' | jq '.["a-b"].["c-d"]'
error: syntax error, unexpected '[', expecting IDENT
.["a-b"].["c-d"]
^
1 compile error

Two questions/possible bugs:

Should ."a-b" work (in the example above)?
How to specify c-d (i.e. nested key with special characters)?

@ghost
Copy link

ghost commented Mar 8, 2014

Okay, so, to settle this question already:

If the key has no special characters, access it like .this.

If the key has special characters, access it like ["this"].

So, @zasran, what you're looking for is .["a-b"]["c-d"].

@zasran
Copy link

zasran commented Mar 10, 2014

Thanks, .["a-b"]["c-d"] does work.

It still looks a bit inconsistent, maybe I don't understand what dot does or something like that (I read the docs at http://stedolan.github.io/jq/manual/).

When there are no special characters this works:

$ echo '{"ab":{"cd":319}}' | jq '.ab.cd'

But if there are special characters it works without the dot (dot actually causes error):

$ echo '{"ab":{"c-d":319}}' | jq '.ab["c-d"]'
319

This seems a bit inconsistent, why is there a dot separator there for non-special character keys and no dot separator when the ["c-d"] format is used? (maybe calling dot separator is not correct but not sure what to call it)

On a similar note, why does the documentation claim that ."foo$" would work (Basic filters section)? As far as I can tell it claims that .foo should be replaced by ."foo$" if the key contains special characters. The .["foo"] version is also mentioned. But what you are saying is that it really should be ["foo$"](no dot).

Example straight from the docs (last .foo example in Basic filters section)):

echo '{"foo": 42}' | jq '."foo"'
error: syntax error, unexpected QQSTRING_START, expecting $end
."foo"
^
1 compile error

Can you please shed some light on this, maybe change the docs so that it's more obvious? Or maybe it's actual bug and it should work as described in the docs?

@nicowilliams
Copy link
Contributor

Dot (.) refers to "the input to the current expression", roughly.

The ."string" syntax (equivalent to .["string"]) is not in a released version, but it is in the master branch.

@nicowilliams
Copy link
Contributor

I'll fix the docs to list what's in 1.3 and what's new since at some point. Also, I think we'll do a new release soon.

@zasran
Copy link

zasran commented Mar 10, 2014

@nicowilliams thanks, that clarifies it!

@akram
Copy link

akram commented May 5, 2014

Hi all,
@nicowilliams
thank you for the great job, this tool really saves me a lot of time.
Unfortunately I am facing this issue, and it seems that a release was planned for soon.
correct me if I am wrong but 1.3 is 1year old.

Do you have an estimate date for 1.4 ?

By the way could you please summarise if a workaroud exist for 1.3 ?
Here is my syntax:
jq ".name.PS_Perm_Gen.peak-usage.init" < /tmp/localhost-localhost-9990-Memory

And, I've tried:
jq .["name.PS_Perm_Gen.peak-usage.init"] < /tmp/localhost-localhost-9990-Memory
error: Invalid numeric literal (while parsing '..')

and that:
jq .name.PS_Perm_Gen.["peak-usage"].init < /tmp/localhost-localhost-9990-Memory
error: syntax error, unexpected '[', expecting IDENT
.name.PS_Perm_Gen.[peak-usage].init

both does not work

greetings
Akram

@nicowilliams
Copy link
Contributor

I didn't finish setting up build envs for Win64 in time and then business
travel intervened. I'll get to it soon, but not this week.

@ghost
Copy link

ghost commented May 14, 2014

@akram jq .name.PS_Perm_Gen["peak-usage"].init is what you're looking for.

There are two syntaxes for element access: .foo and ["foo"]. Note the lack of leading dot in the second case. The second syntax allows for extraneous characters, the first one does not.

If you're using master, as well as in the future 1.4 version, ."foo" is a valid option as well. It also allows extraneous characters.

@hughmandeville
Copy link

Wrap hyphenated name in escaped quotation marks.

jq "[.[]|{\"my-field\"}]" test.json 
[
  {
    "my-field": "val1"
  },
  {
    "my-field": "val2"
  }
]

@ereyes01
Copy link

I think it's important to note that if you ever script the query string to jq, it would be unsafe in the generic case to not use the jq ".[$keyname]" notation if the names of your keys are not statically known/defined. A simple jq ".$keyname" would break if $keyname ever has a hyphen in it.

@ereyes01
Copy link

In fact, it seems like it would be more correct if, in your parser, you would prioritize matching key names over evaluating operators.

example: echo '{"key-10": 10}' | jq ".key-10"

Ideally would print "10"... and:

echo '{"key-10": 10}' | jq ".key-10-10"

would print "0". I say this of course, after having thought about all the possibilities for a full 5 minutes or so :-)

@dtolnay
Copy link
Member

dtolnay commented Sep 20, 2015

Then you have a problem if someone wants to subtract 10 from a key:

echo '{"key": 11, "key-10": 12}' | jq ".${KEY}-10"

This would require the even more confusing ".${KEY}-(10)" or "(.${KEY})-10".

@hexsel
Copy link

hexsel commented Mar 24, 2016

Just for posterity, the following seems to work:

jq .\"a-b\"

Seems like the shortest working query string with a hyphen.

@mcwumbly
Copy link

I ran into this issue today and this workaround in the comment above doesn't seem to work for me in jq 1.3. Anyone have any tips for what works today when strings have dashes in them?

@pkoppstein
Copy link
Contributor

pkoppstein commented Jul 11, 2017

@mcwumbly - The short of it is that, given a JSON object, it's always safe to use the form: .[ $keyname ] where $keyname is a JSON string.

Note also that the fact that .X | .Y works for some X and Y does NOT always mean that .X.Y will work.

For example, .[0] | .["foo-bar"] is valid, but .[0].["foo-bar"] is not.

Alternatively:

$echo '[{ "foo-bar":"baz" }]' | jq '.[0][ "foo-bar" ]'
"baz"

@wtlangford
Copy link
Contributor

wtlangford commented Jul 11, 2017 via email

@mcwumbly
Copy link

thanks @pkoppstein - that helps, and this works:

echo '{ "foo-bar":"baz" }' | jq '.[ "foo-bar" ]'

@pierreprinetti
Copy link

pierreprinetti commented Jul 26, 2017

This works:

echo '[{ "foo-bar":"baz" }]' | jq '.[0]' | jq '.[ "foo-bar" ]'

# "baz"

This doesn't:

echo '[{ "foo-bar":"baz" }]' | jq '.[0].[ "foo-bar" ]'

# jq: error: syntax error, unexpected '[', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
# .[0].[ "foo-bar" ]
# jq: 1 compile error

@nicowilliams
Copy link
Contributor

nicowilliams commented Jul 26, 2017 via email

@pkoppstein
Copy link
Contributor

key="foo-bar"; echo '[{ "foo-bar":"baz" }]' | jq '.[0].[ "$key" ]'

There are two problems with the above. First, the abbreviation .[0].["KEYNAME"] is not (currently) supported. The second has to do with the relationship between the shell or environment variable $key and the jq variable $key.

In a nutshell, here is what is recommended:

key="foo-bar"; echo '[{ "foo-bar":"baz" }]' | jq --arg key "$key" '.[0]|.[ $key ]'

For future reference, please ask usage questions at stackoverflow.com with the jq tag: https://stackoverflow.com/questions/tagged/jq

@dhjw
Copy link

dhjw commented Apr 18, 2019

If you need to pass a variable containing a string with a dash and save it in a variable in a bash script...

result=$(jq --arg a "$query" '.[$a]' -r some.json)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests