Live data from Hacker News

Show HN: Jb / json.bash – Command-line tool (and bash library) that creates JSON

github.com

31–40 of 56 posts

Re: Show HN: Jb / json.bash – Command-line tool (and bash library) that creates JSON

#33
post #30

This is incredibly high-quality BASH programming, as a fellow bash freak I am studying this code, and even I am learning some new techniques. https://github.com/h4l/json.bash/blob/main/json.bash You've boiled it down to a set of very elegant constructs. Respect. Thank you @h4l, this is badass. I hope you follow up with a golang or rust implementation, that would really be something else. p.s. I noticed the following…

Thank you, that's high praise! I learnt a lot about bash writing this, but I've also not looked at the code in a few months, and it's already starting to look quite intimidating!

I definitely like the idea of a goland/rust implementation, there are certainly things I could improve.

So the argument syntax escapes by repeating a character rather than backslash. I chose this because with backslashes escapes it would be unclear whether a backslash was in the shell syntax or the jb syntax, and users may end up needing to double escape backslashes, which is no fun! Whereas a shell will always ignore two copies of a character like =:@.

The downside of double-escaping is that the syntax can be ambiguous, so sometimes you need to include the middle type marker to disambiguate the key from the value. But the type can be empty, so just : works:

    $ jb ===msg==:==hi=
    {"=msg=":"=hi="}
In the key part, the first = begins the key, the == following are an escaped =. The first = following the : marks the value, and everything after is not parsed, so =hi= is literal.

When you have reserved characters in keys/values (especially if they're dynamic), it's easiest to store the values in variables and reference them with @var syntax:

    $ k='=msg=' v='=hi=' jb @k@v
    {"=msg=":"=hi="}

Re: Show HN: Jb / json.bash – Command-line tool (and bash library) that creates JSON

#34

Is there a minimum bash version required? I.e. will it work with bash 3 or whatever ships with macos by default?

There is, the earliest version I've tested with is 4.4.19, but ideally a 5.x version. 3 certainly won't work I'm afraid. If you use homebrew on Mac it's a good way to get the latest bash.

Re: Show HN: Jb / json.bash – Command-line tool (and bash library) that creates JSON

#35
post #26

{"password":"hunter2"} A man of culture I see. This looks really useful where you don't want to introduce another scripting VM just to spit out some JSON, i.e I have used Ruby a lot for this in the past. I can see myself using this in container init scripts and other very low dep environments to format config files from env vars etc.

How did you guess my password?!?!

This is just the kind of use case I had in mind. Something I've considered is publishing a mini version with only the json.encode_string function, as that's enough to create an array of JSON-encoded strings and use a hard-coded template with printf to insert the JSON string values.

That would be a fraction of the overall json.bash file size.

Re: Show HN: Jb / json.bash – Command-line tool (and bash library) that creates JSON

#36
post #2

As well as anyone's general thoughts/experiences, I'd appreciate opinions on the error handling mechanism jb uses to detect errors in upstream jb processes that jb is reading from. Normally, detecting errors on the other end of a pipe requires care in a shell environment (e.g. retrospectively checking PIPESTATUS). I used an approach I've called Stream Poisoning. It takes advantage of the fact that control characters…

What happens if the next program in the pipe is not jb? Does jb also exit with a code? For example `jb | jq`, where jq or a similar program discards the cancel character. (Away from pc, unable to check right now.)

Good question! Yep, jb exits with non-zero:

    $ jb size:number=oops; echo $?
    json.encode_number(): not all inputs are numbers: 'oops'
    json(): Could not encode the value of argument 'size:number=oops' as a 'number' value. Read from inline value.
    ␘
    1
If you pipe the jb error into jq, jq fails to parse the JSON (because of the Cancel ctrl char) and also errors:

    $ jb size:number=oops | jq
    json.encode_number(): not all inputs are numbers: 'oops'
    json(): Could not encode the value of argument 'size:number=oops' as a 'number' value. Read from inline value.
    parse error: Invalid numeric literal at line 2, column 0

    $ declare -p PIPESTATUS
    declare -a PIPESTATUS=([0]="1" [1]="4")
So jq exits with status 4 here.

Re: Show HN: Jb / json.bash – Command-line tool (and bash library) that creates JSON

#37

Yeah if you need this it's definitely a sign you shouldn't be using Bash. Can you give a concrete example of when this is the sanest option?

Two main situations I think. The first is just interactive use in any shell to encode ad-hoc JSON. If you have a next-gen shell which can handle structured data directly, then you probably don't need it.

Second is situations where you'd rather not add an additional dependency, but bash is pretty much a given. For example, CI environments, scripts in dev environments, container entrypoints. Or things that area already written in bash.

I don't advocate writing massive programs in bash, for sure it's better to turn to a proper language before things get hairy. But bash is just really ubiquitous, and most people who do any UNIX work will be able to deal with a bit of shell script.

Re: Show HN: Jb / json.bash – Command-line tool (and bash library) that creates JSON

#38
post #17

Built into Powershell: > @{ hello = 'world' } | ConvertTo-Json > { "hello": "world" }

Not only its built in, but syntax is on another level, i.e. you don't need to learn special syntax if you know PowerShell. This thing alone makes pwsh worth it instead of using number of other tools.

    @{ Hello = 'world'; array = 1..10; object = @{ date = Get-Date } } | ConvertTo-Json
 
    {
      "array": [
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        10
      ],
      "object": {
        "date": "2024-07-03T21:07:21.6562053+02:00"
      },
      "Hello": "world"
    }

Re: Show HN: Jb / json.bash – Command-line tool (and bash library) that creates JSON

#39
post #25
post #17

Built into Powershell: > @{ hello = 'world' } | ConvertTo-Json > { "hello": "world" }

Powershell has the upper hand here! Still, bash can try to keep up using json.bash. :) $ source json.bash $ declare -A greeting=([Hello]=World) $ json ...@greeting:{} {"Hello":"World"} ... is splatting the greeting associative array entries into the object created by the json call. Without the ... the greeting would be a nested object. Probably more clear with multiple entries: $ declare -A greeting=([Hello]=World [H…

    $h=@{x=1; y=2}; $h + @{z=3} | ConvertTo-Json

    {        
      "y": 2,
      "z": 3,
      "x": 1 
    }
You can even use [ordered]$h to make keys not go random place.

Re: Show HN: Jb / json.bash – Command-line tool (and bash library) that creates JSON

#40
post #17

Built into Powershell: > @{ hello = 'world' } | ConvertTo-Json > { "hello": "world" }

Not only its built in, but syntax is on another level, i.e. you don't need to learn special syntax if you know PowerShell. This thing alone makes pwsh worth it instead of using number of other tools. @{ Hello = 'world'; array = 1..10; object = @{ date = Get-Date } } | ConvertTo-Json { "array": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], "object": { "date": "2024-07-03T21:07:21.6562053+02:00" }, "Hello": "world" }

That is pretty cool, and I wish such features were common in regular UNIX shells.

For good measure, this is how you might do the same with jb:

    $ jb Hello=world array:number[]@
Alternatively, using the :{} object entry syntax:

    jb Hello=world array:number[]@
Post reply on HN