Skip to content

Instantly share code, notes, and snippets.

@pkoppstein
Last active August 5, 2021 02:13
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pkoppstein/5eac78d3e9618cfabd7d to your computer and use it in GitHub Desktop.
Save pkoppstein/5eac78d3e9618cfabd7d to your computer and use it in GitHub Desktop.
a commutative and associative operator for combining two JSON objects
# This gist defines a jq filter for combining two JSON objects by resolving conflicts
# in a way that is appropriate for mapping relational tables to objects.
# "combine" as defined here is both commutative and associative.
# Example:
# { "id": 123, "son": "Son1", "surname": "S"}
# | combine({ "id": 123, "son": "Son2", "surname": "S"})
# produces: { "id": 123, "son": ["Son1",Son2], "surname": "S"}
# Combine two entities in an array-oriented fashion.
# If uniq is true, then pass the results of the following through unique:
# if both are arrays: a + b
# else if a is an array: a + [b]
# else if b is an array: [a] + b
# else [a, b]
def aggregate(a;b;uniq):
if uniq then aggregate(a; b; false) | unique
elif (a|type) == "array" then
if (b|type) == "array" then a + b
else a + [b]
end
else
if (b|type) == "array" then [a] + b
else [a, b]
end
end;
# Combine . with obj using aggregate/3 for shared keys whose values differ
def combine(obj):
. as $in
| reduce (obj|keys|.[]) as $key
($in;
if .[$key] == obj[$key] then .
else setpath([$key];
aggregate( $in|getpath([$key]); obj|getpath([$key]); true ) )
end ) ;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment