I tried accessing the object using both the generic object index and the shorthand version of it but it appears that the generic object index won't work. Can someone explain to me why?
I have the following json file jsonsample.txt
{
"id": "v4cw72hf3",
"output": {
"url": "//srv01.cloudconvert.com/download/~ugl5vnrpfO",
"downloads": 0
},
}
The Jq manual explained the generic syntax
Generic Object Index: .[<string>]
You can also look up fields of an object using syntax like .["foo"] (.foo above is a shorthand version of this, but only for identifier-like strings).
and I tried two ways to access the url field
jq '["output"].["url"]' jsonsample.txt
jq .output.url jsonsample.txt
But the first one doesn't give me the desired results
#Result for the first line
jq: error: syntax error, unexpected '[', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.["output"].["url"]
jq: 1 compile error
shell returned 3
#Results for the second line
"//srv01.cloudconvert.com/download/~ugl5vnrpfO"
The input is not quite valid JSON, so the following assumes it has been fixed.
The basic form for a pipeline of array and/or object accessors is
.[<string-or-integer>] | .[<string-or-integer>] | ...
So you'd be safe with .["output"]|.["url"]
Certain abbreviations are allowed, but different versions of jq differ in the details. However, it's generally safe to remove an interior |., i.e. one would expect
.["output"]["url"]
to work, as indeed it does going back at least to jq 1.3.
The restricted .foo.bar notation is also supported going back at least to jq 1.3.
jq 1.4 added support for unrestricted dot-string notation wherein the key name can be any valid JSON string (i.e. with quotation marks), e.g.
."foo with space"."bar with space"
Related
I have the following JISON file (lite version of my actual file, but reproduces my problem):
%lex
%%
"do" return 'DO';
[a-zA-Z_][a-zA-Z0-9_]* return 'ID';
"::" return 'DOUBLECOLON'
<<EOF>> return 'ENDOFFILE';
/lex
%%
start
: ID DOUBLECOLON ID ENDOFFILE
{$$ = {type: "enumval", enum: $1, val: $3}}
;
It is for parsing something like "AnimalTypes::cat". It works fine for things like "AnimalTypes::cat", but the when it sees dog instead of cat, it asumes it's a DO instead of an id. I can see why it does that, but how do I get around it? I've been looking at other JISON documents, but can't seem to spot the difference that (I assume) makes those work.
This is the error I get:
JisonParserError: Parse error on line 1:
PetTypes::dog
----------^
Expecting "ID", "enumstr", "id", got unexpected "DO"
Repro steps:
Install jison-gho globally from npm (or modify code to use local version). I use Node v14.6.0.
Save the JISON above as minimal-repro.jison
Run: jison -m es -o ./minimal.mjs ./minimal-repro.jison to create parser
Create a file named test.mjs with code like:
import Parser from "./minimal.mjs";
Parser.parser.parse("PetTypes::dog")
Run node test.mjs
Edit: Updated with a reproducible example.
Edit2: Simpler JISON
Unlike (f)lex, the jison lexer accepts the first matching pattern, even if it is not the longest matching pattern. You can get the (f)lex behaviour by using
%option flex
However, that significantly slows down the scanner.
The original jison automatically added \b to the end of patterns which ended with a literal string matching an alphabetic character, to make it easier to match keywords without incurring this overhead. In jison-gho, this feature was turned off unless you specify
%option easy_keyword_rules
See https://github.com/zaach/jison/wiki/Deviations-From-Flex-Bison#user-content-literal-tokens.
So either of those options will achieve the behaviour you expect.
I'm using bash 4.4.19(1)-release.
At the start of my program I read customer configuration values from the command line, configuration file(s), and the environment (in decreasing order of precedence). I validate these configuration values against internal definitions, failing out if required values are missing or if the customer values don't match against accepted regular expressions. This approach is a hard requirement and I'm stuck using BASH for this.
The whole configuration process involves the parsing of several YAML files and takes about a second to complete. I'd like to only have to do this once in order to preserve performance. Upon completion, all of the configured values are placed in a global associative array declared as follows:
declare -gA CONFIG_VALUES
A basic helper function has been written for accessing this array:
# A wrapper for accessing the CONFIG_VALUES array.
function get_config_value {
local key="${1^^}"
local output
output="${CONFIG_VALUES[${key}]}"
echo "$output"
}
This works perfectly fine when all of the commands are run within the same shell. This even works when the get_config_value function is called from a child process. Where this breaks down is when it's called from a child process and the value in the array contains slashes. This leads to errors such as the following (line 156 is "output="${CONFIG_VALUES[${key}]}"):
config.sh: line 156: path/to/some/file: syntax error: operand expected (error token is "/to/some/file")
This is particularly obnoxious because it seems to be reading the value "path/to/some/file" just fine. It simply decides to announce a syntax error after doing so and falls over dead instead of echoing the value.
I've been trying to circumvent this by running the array lookup in a subshell, capturing the syntax failure, and grepping it for the value I need:
# A wrapper for accessing the CONFIG_VALUES array.
function get_config_value {
local key="${1^^}"
local output
if output="$(echo "${CONFIG_VALUES[${key}]}" 2>&1)"; then
echo "$output"
else
grep -oP "(?<=: ).*(?=: syntax error: operand expected)" <<< "$output"
fi
}
Unfortunately, it seems that BASH won't let me ignore the "syntax error" like that. I'm not sure where to go from here (well... Python, but I don't get to make that decision).
Any ideas?
So, I am writing a shell script and I am running a command that gives me an output like:
{"a":"some_text","b":some_other_text","c":"even_more_text"}
Now, I am not sure how to parse it, I basically need the value of "c", i.e. "ever_more_text" in a variable, but finding out results on internet have not worked yet! TIA.
the output which you paste here is not valid json. Check with https://jsonformatter.curiousconcept.com/ There is missing first double quote in "some_other_text". If you add it, you can then easily parse with jq:
./your_script.sh | jq -r ".c"
This question already has answers here:
jq not working on tag name with dashes and numbers
(2 answers)
Closed 4 years ago.
I have a (not so complicated) json file and I need to extract its contents using bash. I want to use jq for the processing, it should be straightforward. The problem is that I'm getting a weird error in the processing that I don't know how to solve (because I don't know what is causing it).
A minimal sample causing me problems:
{
"E23763": {
"data": "information"
}
}
If I just run jq to pretty-print it, it works:
$ cat test.json | jq .
{
"E23763": {
"data": "information"
}
}
But if I try to extract the first field, it fails criptically:
$ cat test.json | jq .E23763
jq: error: Invalid numeric literal at EOF at line 1, column 7 (while parsing '.E23763') at <top-level>, line 1:
.E23763
jq: 1 compile error
The expected result would had been:
{
"data": "information"
}
Anyone found a similar issue? Why it is complaining about a numeric literal when he is really looking into a string?
Quotation didn't seem to matter here, same error.
Please refer to this issue on GitHub there are many responses posted here which might help you with your problem: https://github.com/stedolan/jq/issues/1526
I'll post one of the solutions here however:
jq '.["E23763"]' test.json
Another Solution as said by #Inian is:
jq '."E23763"' json
Without the [], in this case it was the correct solution but try both nonetheless
Basically the parser is buggy and treats .E as the beginning of a number.
This question already has answers here:
jq not working on tag name with dashes and numbers
(2 answers)
Closed 5 years ago.
I have a REST API, which returns something like this:
{
"foo": 1,
"bar": 2,
"foo-bar": 3
}
when I do `http /endpoint/url | jq '.foo-bar', it gave the following error:
jq: error (at <stdin>:1): null (null) and boolean (true) cannot be subtracted
it looks like jq thinks I'm trying to do arithmetic operation with foo-bar.
How do I correctly form this kind of path? Or this is a bug of jq?
In JSON text, JSON keys are always double-quoted. Perhaps your REST API was formatting it properly in double-quotes and your example in your last edit was incorrect. Because without the same jq cannot parse the syntax as a valid JSON.
As far the issue you are seeing, you need to put the field within quotes to let jq know that it is a single field foo-bar you are accessing and not as separate fields
jq '."foo-bar"'
Or more specifically use the array access operator as jq '.["foo-bar"]'