tomnomnom / gron

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

Multiple files or urls as input #28

Open ghost opened 6 years ago

ghost commented 6 years ago

This relates to multiple objects in the same input, but is a bit different.

Would be useful to allow more than one input on the command line:

gron <file|url> <file|url> ... etc

It's hard to say exactly what gron should output in this case, possibly each object field could inherit the file or url name.

e.g.

gron file1.json file2.json

file1.keyValue = "fish" file2.keyValue = "chips"

or perhaps more simply, number the files, which would avoid file name clashes (and could also support multiple objects in streams.)

[0].keyValue = "fish" [1].keyValue = "chips"

at the moment, I for this, which isn't quite as good: echo *.json | xargs -n1 gron >> out.txt

tomnomnom commented 6 years ago

Hi @jspashett! Thanks for submitting an issue :)

I think it would make sense to use the same behaviour as the stream mode in this case; i.e. treating each file as an item in an array like this:

▶ echo -e '{"one": 1}\n{"two": 2}\n{"three":3}' | gron --stream
json = [];
json[0] = {};
json[0].one = 1;
json[1] = {};
json[1].two = 2;
json[2] = {};
json[2].three = 3;

I think what might be tricky here is figuring out what happens when the stream mode is used by multiple files. I'll give that some thought and get back to you if that's OK? :)

ghost commented 6 years ago

Here are some suggestions. "Stream" might be the wrong word, perhaps they should be called documents?

say file1 has 3 separate json objects within it. and file2 is a single json object

gron file1 file2

(a)

... json[0][0] = {}; // file1, stream 0 json[0][1] = {}; // file1, stream 1 json[0][2] = {}; // file1, stream 2 json[1][0] = {}; // file2, stream 0 ...

(b) Just number them as you would anyway.

json[0] = {}; // file1, stream 0 json[1] = {}; // file1, stream 1 json[2] = {}; // file1, stream 2 json[3] = {}; // file2, stream 0

(c) Like a or b but add a comment line saying what the source was. e.g.:

// file1.txt, stream 0 json[0][0] = {}; // http://json.org, stream 0 json[1][0] = {};

In (a) you can tell which file and which object something comes from. in (b), you can't but it is simpler.

tomnomnom commented 6 years ago

@jspashett Ah, I wasn't very clear about what I meant there sorry! I think your option (a) is the right approach, but I was thinking more about how I would implemented it in the code; hah.

Thanks!

superuser5 commented 3 years ago

another example for this improvement: gron -s .json user gron -s logs_.json user gron -s _2020-09-04T1?0306Z.json -> use for wildcard match and ? for digit match

mbafford commented 2 years ago

Throwing my thoughts/desire behind this enhancement.

I just ran into a case where this would be very helpful. In my case, I had multiple files all of the same general structure, so I basically wanted this:

gron -s *.json

to act like this:

jq -c . *.json | gron -s

(jq -c converting each JSON file into a single line)

producing:

json[0] = {};
json[0].brand_name = "Specialized";
json[1] = {};
json[1].brand_name = "Specialized";
json[2] = {};
json[2].brand_name = "Specialized";

I think in the case of multiple files being displayed, the -s is effectively implicit.

Alternately, require -s to achieve the results above, and have the default behavior be more like looping over and running gron on each file individually, then storing at the top-level keyed by filename:

json["b1234.meta.json"][0] = {};
json["b1234.meta.json"][0].brand_name = "Specialized";
json["a5221.meta.json"][0] = {};
json["a5221.meta.json"][0].brand_name = "Specialized";
json["a5221.meta.json"][1] = {};
json["a5221.meta.json"][1].brand_name = "Specialized";

I would think the keys here would be either the filename or the provided path. But have a flag to switch behavior.

sputnick-dev commented 1 year ago

IMHO, gron should behave like jq: process multiple files as input. Related: https://stackoverflow.com/a/75475604/465183