jmespath / jmespath/jmespath.jep

Spec change - merge() function

Open
#4 2 comments 1 reaction 0 assignees View on GitHub
Dominant language
Python
Stars
10
Forks
3
PR merge metrics
No merged PRs in 30d

Description

## Background

In all the example given in the spec page for the [merge()](https://jmespath.org/specification.html#merge) function`LITERAL` types are provided as arguments to the function. While this demonstrates the behaviour it is **not at all** useful in practical terms. Literals can only be explicitly defined by the editor of an expression. Much more useful would be to merge on results of expressions or on projections.

### Examples:

```javascript
search([{a: "AY", x: "EX"}, {a: "EY", b: "BEE"}], 'merge(@)')
// OUTPUTS: {"a": "EY", "b": "BEE", "x": "EX"}

search([{a: "AY", x: "EX"}, {a: "EY", b: "BEE"}], 'merge([{FED: @[0].x}, {BAR: @[1].b}])')
// OUTPUTS: {"BAR": "BEE", "FED": "EX"}

```

In order to do this merge would have to accept either TYPE_OBJECT or TYPE_ARRAY to work and the function would need to be able to switch on either type to handle this.

### Discussion

Array can contain any value and ideally we may want to restrict it to a new `TYPE_ARRAY_OBJECT` type so that we can guarantee only objects can be used in the merge. One interesting side effect of this in javascript is that merging arrays results in array members being keyed in their index. This means we can do the following with very little code change:

```javascript
search([{"A": "ONE"}, "TWO", {"C": "THREE"}], 'merge(@)')
// OUTPUTS: {"0": "ZERO", "A": "ONE", "C": "THREE"}

// With all JSON array member types:

search([{"A": "ONE"}, true, null, "BAR", ["ZERO"], 666], 'merge(@)')
// OUTPUTS: {"0": "ZERO", "1": "A", "2": "R", "A": "ONE"}
```

## Implementation in jmespath.ts

```javascript
// Runtime
private functionMerge: RuntimeFunction = resolvedArgs => {
let merged = {};
for (let i = 0; i < resolvedArgs.length; i += 1) {
const current = resolvedArgs[i];
if (Array.isArray(current)) {
merged = Object.assign(merged, ...current);
} else {
merged = Object.assign(merged, current);
}
}
return merged;
};

// and in the function table

merge: {
_func: this.functionMerge,
_signature: [
{
types: [InputArgument.TYPE_OBJECT, InputArgument.TYPE_ARRAY],
variadic: true,
},
],
},

```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.