-
Notifications
You must be signed in to change notification settings - Fork 67
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
Handling JSON-compatible pseudo-maps #4565
Comments
I recently bumped into another variation of this while helping a user in a community Slack thread. Their specific example:
This shows how they had to piece together the same kind of I did come up with this one alternative that was fewer steps, though maybe not much less code.
We had some more chat about whether it would make sense to have functionality to achieve this more directly, e.g., as the user put it:
In thinking it over, part of why this doesn't show up so directly even in other languages like Python is because data like this user's that's a record with a single key/value pair is basically a simplification of the general case. A record in Zed (or a dict in Python, an object in JavaScript, etc.) can potentially have many key value pairs, hence why the built-in approaches often take the form of "give me all the keys, and I'll iterate through them to filter out the one I want". But it can still be true that a more direct way to handle the simple case would be handy, even if it was just something delivered via a module (#2599) when that becomes an option. In thinking about user-defined functionality that could fit into a module, I proposed this alternative:
And if it needed to be in a single value, add
And if you truly wanted just a JSON-style record/object like we had before, you could use
Part of why I fiddled with a map is because a straight
If you happen to know the number of
But I don't see a quick way for the general case, i.e. no way to |
Repro is with Zed commit 4ffdf3e.
Consider again the
jq
example with test data scan.json.gz shown at the top of #4555 and the Zed that tries to come close to it.A subtle difference is that the
zq
output is two separate records while thejq
output is a single JSON object. There's nothing about the JSON object output byjq
that says it must ultimately be used like a map, but docs like Go'sjson.Marshal()
(and the equivalent in other languages) set expectations about bouncing between this JSON representation and a truemap
within a language.Imagining I was a user insistent on matching the
jq
output, I struggled to easily replicate the same output withzq
. Zed'scollect()
andunion()
will consolidate values, but they produce arecord
orset
, respectively. Zed'smap
type seems the likely match, but once it's assembled and output as JSON, it comes out with namedkey
andvalue
fields which once again is a mismatch from what we saw withjq
.The team did eventually come up with this approach that matches the
jq
output, but it's probably not something we can expect our current user base to come up with on their own. (Output has been pretty-printed for readability.)Unless I'm missing something obvious, it does seem like we could stand to improve here. A few ideas:
Instead of always using the
key
/value
representation, perhaps the JSON output of a Zedmap
could instead be in this pseudo-map object form. If there's something about the data that prevents it from being output that way (e.g., keys that aren't simple strings and can't be easily cast into them) that could surface an error so the user knows they'd need to transform the data. (Update: Since the opening of this issue, Improve JSON output for Zed maps #4589 has covered this.)If we offer that and then a user is reliant on having access to the
key
/value
representation in order to do their transforms, perhaps theflatten()
function could be enhanced to acceptmap
types as input, or have a separate function to handle this flattening of maps.Once it becomes easier to write this kind of output as JSON, I imagine we'll want ways to easily read it back in as
map
types. At the moment the way I can see to turn such a pseudo-map back into a Zed map isover this | collect_map(|{key[0]:value}|)
, but to make this easier perhaps thecollect_map()
aggregate function could be enhanced to directly accept a record as input with handling, similar to Go'sjson.Unmarshal()
.The text was updated successfully, but these errors were encountered: