mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-20 16:43:53 +01:00
Add an option to allow jsonpath/xpath to return as array (#297)
Co-authored-by: Gregory Schier <gschier1990@gmail.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
"description": "Template functions for working with JSON data",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"build": "yaakcli build",
|
||||
"dev": "yaakcli dev",
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import type { XPathResult } from '@yaak/template-function-xml';
|
||||
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
import { JSONPath } from 'jsonpath-plus';
|
||||
|
||||
const RETURN_FIRST = 'first';
|
||||
const RETURN_ALL = 'all';
|
||||
const RETURN_JOIN = 'join';
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
templateFunctions: [
|
||||
{
|
||||
@@ -8,32 +13,59 @@ export const plugin: PluginDefinition = {
|
||||
description: 'Filter JSON-formatted text using JSONPath syntax',
|
||||
args: [
|
||||
{
|
||||
type: 'text',
|
||||
type: 'editor',
|
||||
name: 'input',
|
||||
label: 'Input',
|
||||
multiLine: true,
|
||||
language: 'json',
|
||||
placeholder: '{ "foo": "bar" }',
|
||||
},
|
||||
{
|
||||
type: 'h_stack',
|
||||
inputs: [
|
||||
{
|
||||
type: 'select',
|
||||
name: 'result',
|
||||
label: 'Return Format',
|
||||
defaultValue: RETURN_FIRST,
|
||||
options: [
|
||||
{ label: 'First result', value: RETURN_FIRST },
|
||||
{ label: 'All results', value: RETURN_ALL },
|
||||
{ label: 'Join with separator', value: RETURN_JOIN },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'join',
|
||||
type: 'text',
|
||||
label: 'Separator',
|
||||
optional: true,
|
||||
defaultValue: ', ',
|
||||
dynamic(_ctx, args) {
|
||||
return { hidden: args.values.result !== RETURN_JOIN };
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'checkbox',
|
||||
name: 'formatted',
|
||||
label: 'Pretty Print',
|
||||
description: 'Format the output as JSON',
|
||||
dynamic(_ctx, args) {
|
||||
return { hidden: args.values.result === RETURN_JOIN };
|
||||
},
|
||||
},
|
||||
{ type: 'text', name: 'query', label: 'Query', placeholder: '$..foo' },
|
||||
{ type: 'checkbox', name: 'formatted', label: 'Format Output' },
|
||||
],
|
||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
try {
|
||||
const parsed = JSON.parse(String(args.values.input));
|
||||
const query = String(args.values.query ?? '$').trim();
|
||||
let filtered = JSONPath({ path: query, json: parsed });
|
||||
if (Array.isArray(filtered)) {
|
||||
filtered = filtered[0];
|
||||
}
|
||||
if (typeof filtered === 'string') {
|
||||
return filtered;
|
||||
}
|
||||
|
||||
if (args.values.formatted) {
|
||||
return JSON.stringify(filtered, null, 2);
|
||||
} else {
|
||||
return JSON.stringify(filtered);
|
||||
}
|
||||
console.log('formatted', args.values.formatted);
|
||||
return filterJSONPath(
|
||||
String(args.values.input),
|
||||
String(args.values.query),
|
||||
(args.values.result || RETURN_FIRST) as XPathResult,
|
||||
args.values.join == null ? null : String(args.values.join),
|
||||
Boolean(args.values.formatted),
|
||||
);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
@@ -79,3 +111,41 @@ export const plugin: PluginDefinition = {
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export type JSONPathResult = 'first' | 'join' | 'all';
|
||||
|
||||
export function filterJSONPath(
|
||||
body: string,
|
||||
path: string,
|
||||
result: JSONPathResult,
|
||||
join: string | null,
|
||||
formatted: boolean = false,
|
||||
): string {
|
||||
const parsed = JSON.parse(body);
|
||||
let items = JSONPath({ path, json: parsed });
|
||||
|
||||
if (items == null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!Array.isArray(items)) {
|
||||
// Already good
|
||||
} else if (result === 'first') {
|
||||
items = items[0] ?? '';
|
||||
} else if (result === 'join') {
|
||||
items = items.map((i) => objToStr(i, false)).join(join ?? '');
|
||||
}
|
||||
|
||||
return objToStr(items, formatted);
|
||||
}
|
||||
|
||||
function objToStr(o: unknown, formatted: boolean = false): string {
|
||||
if (
|
||||
Object.prototype.toString.call(o) === '[object Array]' ||
|
||||
Object.prototype.toString.call(o) === '[object Object]'
|
||||
) {
|
||||
return formatted ? JSON.stringify(o, null, 2) : JSON.stringify(o);
|
||||
} else {
|
||||
return String(o);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user