tomnomnom / gron

Make JSON greppable!
MIT License
13.83k stars 327 forks source link

--no-sort option is unstable #102

Open slafs opened 2 years ago

slafs commented 2 years ago

For a simple JSON doc

{"z": "first", "a": "last"}

gron --no-sort keeps producing wrong results at around 12% rate.

Tried it with:

$ for i in $( seq 1000 ); do echo '{"z": "first", "a": "last"}' | gron --no-sort | column -x; done | sort | uniq -c
 125 json = {};     json.a = "last";    json.z = "first";
 875 json = {};     json.z = "first";   json.a = "last";

Tried it with:

$ gron --version
gron version dev
$ brew info gron
gron: stable 0.7.1 (bottled), HEAD
Make JSON greppable
https://github.com/tomnomnom/gron
/usr/local/Cellar/gron/0.7.1 (4 files, 5MB) *
  Poured from bottle on 2022-06-29 at 13:56:51
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/gron.rb
License: MIT
==> Dependencies
Build: go ✘
==> Options
--HEAD
    Install HEAD version
==> Analytics
install: 878 (30 days), 2,899 (90 days), 5,560 (365 days)
install-on-request: 876 (30 days), 2,899 (90 days), 5,561 (365 days)
build-error: 0 (30 days)

$ brew list gron
/usr/local/Cellar/gron/0.7.1/bin/gron
slafs commented 2 years ago

BTW this tool is fantastic and helps me a lot! Thanks for creating it :)

RossPatterson commented 2 years ago

--no-sort tells gron not to sort the output. It doesn't guarantee a stable order - if you want that, let it sort. The instability comes from the underlying Go map object, which randomizes string hashing functions.

slafs commented 2 years ago

Well, I guessed that might be the cause, but the underlying implementation shouldn't matter, right? The option is confusing when it works this way. What's the use of a non-sorted output if the input is being modified in the first place 😅?

adamritter commented 1 year ago

Hi, I just tried with the tool I wrote ( https://github.com/adamritter/fastgron ), it preserves the order with gron (I'm not sure about ungron though yet :( )

for i in $( seq 1000 ); do echo '{"z": "first", "a": "last"}' | gron --no-sort | column -x; done | sort | uniq -c;

130 json = {}; json.a = "last"; json.z = "first"; 870 json = {}; json.z = "first"; json.a = "last"; (base) ➜ ~/Documents/GitHub/fastgron/fastgron git:(main) for i in $( seq 1000 ); do echo '{"z": "first", "a": "last"}' | fastgron --no-sort | column -x; done | sort | uniq -c;

1000 json = {} json.z = "first" json.a = "last"

dhimmel commented 9 months ago

+1 to --no-sort preserving input order if that's not to difficult to implement. Right now there is no way to retain order, but order often is often explicitly set in JSON objects to aid in interpretation / human-legibility.