-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
How to make jq ignore invalid JSON and keep the original (non-JSON) output? #1547
Comments
In your particular case, you could simply add -r to the command-line switches:
The -r option causes top-level JSON strings to be printed as "raw" strings, so if you only want the erroneous lines to be printed in "raw" mode, a more complex solution will be required, but it is easily doable. For future reference, please ask usage questions at stackoverflow.com with the jq tag: |
Can you clarify this? Example, $ echo '[nodemon] 1.18.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: /Users/gajus/Documents/dev/applaudience/showtime-api/src/**/*
[nodemon] starting `"babel-node" src/bin/server.js`' | jq -crRC 'fromjson? | select(.context.logLevel > 20)'
does not print anything, whereas I expect it to simply print the input. |
The closest thing I got to printing raw text and JSON is: $ echo '[nodemon] 1.18.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: /Users/gajus/Documents/dev/applaudience/showtime-api/src/**/*
[nodemon] starting `"babel-node" src/bin/server.js`
{"foo":"bar"}
' | jq -crRC '. as $raw | try fromjson catch $raw'
[nodemon] 1.18.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: /Users/gajus/Documents/dev/applaudience/showtime-api/src/**/*
[nodemon] starting `"babel-node" src/bin/server.js`
{"foo":"bar"} But now three appears to be no way to terminate the output at the $ $ echo '[nodemon] 1.18.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: /Users/gajus/Documents/dev/applaudience/showtime-api/src/**/*
[nodemon] starting `"babel-node" src/bin/server.js`
{"foo":"bar"}
' | jq -crRC '. as $raw | try fromjson catch $raw | .? | select(.foo = "bar")'
The expected output is:
The actual output is:
How do I force print at the catch clause? |
@gajus - Unfortunately you seem to have completely misunderstood the sentence in which the clauses you quote ("a more complex solution will be required, but it is easily doable") appear. In any case, you might like to try this:
For future reference, please ask usage questions (including followup questions regarding the above) at stackoverflow.com using the |
@gajus - I'm seconding @pkoppstein, his example works great:
|
Don't like this solution because it requires to wrap everything in a I think that jq should have a keyword/ function such as |
@gajus - Thank you for closing this trouble ticket. From your last comment, it is evident that you are still having trouble understanding the flow of data in jq filters. Also, I think your comments about try/catch might reflect some misunderstanding of this feature. Perhaps these examples will help:
However, you are right that this solution is limited -- in effect, it assumes that each valid JSON entity occurs on a single line. That is, its applicability is effectively limited to JSONL that has been interspersed with lines of text. |
I see this is an old issue, still it makes me nervous that adding bogus features for solving the the wrong problem is even discussed. As a reminder the problem statement is:
Taken at face value, there is probably no way around of relying on the power of
For probably most reasonably written software, valid json logs should be distinguishable by just looking at the first character: if it's not a
That's valid json but probably not what the opener of this issue wanted to parse as a valid log entry. So I suggest doing what is unix standard and what proper programs should do in the first place: redirect diagnostic messages to stderr. Ok, one can argue that logs are "diagnostic messages" by definition, but I think we can agree that there is still a semantic difference between startup/shutdown or other exceptional output and actual log messages which are usually processed further down the pipeline (which is why we use json in the first place). But what if you can't fix the original program? Then you can work around it by doing the right thing yourself, e.g. awk can easily redirect non-matching lines to stderr: $ echo '[nodemon] 1.18.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: /Users/gajus/Documents/dev/applaudience/showtime-api/src/**/*
[nodemon] starting `"babel-node" src/bin/server.js`
{"foo":"bar"}' | awk '/^{/{print; fflush(); next} {print >"/dev/stderr" }'| jq
This also has the advantage that you can still distinguish between json logs and other output and redirect the stderr stream to somewhere else (or you do it directly in |
For future folks who come by (including myself), this is what I did:
It filters out anything that doesn't start with a |
Sure that's an easy way which should cover a lot of usecases. But the question was about how to keep the original output, hence my suggestion of redirecting non-matching lines to stderr. A combination of shell functions I like to use is rederr()(set -o pipefail;"$@" 2>&1 >&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1
j() { awk '/^{/{print; fflush(); next} {print >"/dev/stderr" }'; } which you can use like this
and if your terminal supports color, you can easily distinguish the non-json output by its red color . |
Code:
Output:
|
e.g.
I have a program that outputs:
I want jq to parse the JSON lines and leave the non-JSON output untouched.
First, I have tried using
--seq
:Using
--seq
produces no output.Then I tried using
fromjson
:This method excludes the non-JSON output.
Then I have tried the
try .. catch
approach:The problem with the output here is that the original non-JSON output received quotes, i.e.
test
became"test"
.How to make jq ignore invalid JSON and keep the original (non-JSON) output?
The text was updated successfully, but these errors were encountered: