Skip to content

Commit 4015507

Browse files
committed
feat: JSONPath and JQ memo
1 parent 0d9f6aa commit 4015507

File tree

9 files changed

+256
-10
lines changed

9 files changed

+256
-10
lines changed

components.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,11 @@ declare module '@vue/runtime-core' {
107107
Ipv4RangeExpander: typeof import('./src/tools/ipv4-range-expander/ipv4-range-expander.vue')['default']
108108
Ipv4SubnetCalculator: typeof import('./src/tools/ipv4-subnet-calculator/ipv4-subnet-calculator.vue')['default']
109109
Ipv6UlaGenerator: typeof import('./src/tools/ipv6-ula-generator/ipv6-ula-generator.vue')['default']
110+
JqMemo: typeof import('./src/tools/jq-memo/jq-memo.md')['default']
110111
JqTester: typeof import('./src/tools/jq-tester/jq-tester.vue')['default']
111112
JsonDiff: typeof import('./src/tools/json-diff/json-diff.vue')['default']
112113
JsonMinify: typeof import('./src/tools/json-minify/json-minify.vue')['default']
114+
JsonpathMemo: typeof import('./src/tools/jsonpath-memo/jsonpath-memo.md')['default']
113115
JsonToCsv: typeof import('./src/tools/json-to-csv/json-to-csv.vue')['default']
114116
JsonToToml: typeof import('./src/tools/json-to-toml/json-to-toml.vue')['default']
115117
JsonToXml: typeof import('./src/tools/json-to-xml/json-to-xml.vue')['default']

src/tools/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { tool as base64StringConverter } from './base64-string-converter';
33
import { tool as basicAuthGenerator } from './basic-auth-generator';
44
import { tool as emailNormalizer } from './email-normalizer';
55
import { tool as jqTester } from './jq-tester';
6+
import { tool as jsonpathMemo } from './jsonpath-memo';
7+
import { tool as jqMemo } from './jq-memo';
68

79
import { tool as asciiTextDrawer } from './ascii-text-drawer';
810

@@ -156,6 +158,8 @@ export const toolsByCategory: ToolCategory[] = [
156158
yamlViewer,
157159
emailNormalizer,
158160
jqTester,
161+
jqMemo,
162+
jsonpathMemo,
159163
],
160164
},
161165
{

src/tools/jq-memo/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Brackets } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Jq Cheatsheet',
6+
path: '/jq-memo',
7+
description: 'JQ command cheatsheet',
8+
keywords: ['jq', 'cheatsheet', 'memo'],
9+
component: () => import('./jq-memo.vue'),
10+
icon: Brackets,
11+
createdAt: new Date('2024-08-15'),
12+
});

src/tools/jq-memo/jq-memo.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Processing JSON using jq
2+
3+
jq is useful to slice, filter, map and transform structured json data.
4+
5+
## Installing jq
6+
7+
### On Mac OS
8+
9+
`brew install jq`
10+
11+
### On AWS Linux
12+
13+
Not available as yum install on our current AMI. It should be on the latest AMI though: https://aws.amazon.com/amazon-linux-ami/2015.09-release-notes/
14+
15+
Installing from the source proved to be tricky.
16+
17+
## Useful arguments
18+
19+
When running jq, the following arguments may become handy:
20+
21+
| Argument | Description |
22+
| ------ | :--------- |
23+
| `--version`| Output the jq version and exit with zero. |
24+
| `--sort-keys` | Output the fields of each object with the keys in sorted order.|
25+
26+
## Basic concepts
27+
28+
The syntax for jq is pretty coherent:
29+
30+
| Syntax | Description |
31+
| ------ | :--------- |
32+
| , | Filters separated by a comma will produce multiple independent outputs|
33+
| ? | Will ignores error if the type is unexpected |
34+
| [] | Array construction |
35+
| {} | Object construction |
36+
| + | Concatenate or Add |
37+
| - | Difference of sets or Substract |
38+
| length | Size of selected element |
39+
| | | Pipes are used to chain commands in a similar fashion than bash|
40+
41+
42+
## Dealing with json objects
43+
44+
| Description | Command |
45+
| ------ | :--------- |
46+
| Display all keys | `jq 'keys'` |
47+
| Adds + 1 to all items | `jq 'map_values(.+1)'` |
48+
| Delete a key| `jq 'del(.foo)'` |
49+
| Convert an object to array | `to_entries | map([.key, .value])` |
50+
51+
## Dealing with fields
52+
53+
| Description | Command |
54+
| ------ | :--------- |
55+
| Concatenate two fields| `fieldNew=.field1+' '+.field2` |
56+
57+
58+
## Dealing with json arrays
59+
60+
### Slicing and Filtering
61+
62+
| Description | Command |
63+
| ------ | :--------- |
64+
| All | `jq .[]` |
65+
| First | `jq '.[0]'` |
66+
| Range | `jq '.[2:4]'` |
67+
| First 3 | `jq '.[:3]'` |
68+
| Last 2 | `jq '.[-2:]'` |
69+
| Before Last | `jq '.[-2]'`|
70+
| Select array of int by value | `jq 'map(select(. >= 2))'` |
71+
| Select array of objects by value| `jq '.[] | select(.id == "second")'` |
72+
| Select by type | `jq '.[] | numbers'` with type been arrays, objects, iterables, booleans, numbers, normals, finites, strings, nulls, values, scalars |
73+
74+
### Mapping and Transforming
75+
76+
| Description | Command |
77+
| ------ | :--------- |
78+
| Add + 1 to all items | `jq 'map(.+1)'` |
79+
| Delete 2 items| `jq 'del(.[1, 2])'` |
80+
| Concatenate arrays | `jq 'add'` |
81+
| Flatten an array | `jq 'flatten'` |
82+
| Create a range of numbers | `jq '[range(2;4)]'` |
83+
| Display the type of each item| `jq 'map(type)'` |
84+
| Sort an array of basic type| `jq 'sort'` |
85+
| Sort an array of objects | `jq 'sort_by(.foo)'` |
86+
| Group by a key - opposite to flatten | `jq 'group_by(.foo)'` |
87+
| Minimun value of an array| `jq 'min'` .See also min, max, min_by(path_exp), max_by(path_exp) |
88+
| Remove duplicates| `jq 'unique'` or `jq 'unique_by(.foo)'` or `jq 'unique_by(length)'` |
89+
| Reverse an array | `jq 'reverse'` |

src/tools/jq-memo/jq-memo.vue

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<script setup lang="ts">
2+
import { useThemeVars } from 'naive-ui';
3+
import Memo from './jq-memo.md';
4+
5+
const themeVars = useThemeVars();
6+
</script>
7+
8+
<template>
9+
<div>
10+
<Memo style="overflow-x: auto;" />
11+
</div>
12+
</template>
13+
14+
<style lang="less" scoped>
15+
::v-deep(pre) {
16+
margin: 0;
17+
padding: 15px 22px;
18+
background-color: v-bind('themeVars.cardColor');
19+
border-radius: 4px;
20+
overflow: auto;
21+
}
22+
::v-deep(table) {
23+
border-collapse: collapse;
24+
}
25+
::v-deep(table), ::v-deep(td), ::v-deep(th) {
26+
border: 1px solid v-bind('themeVars.textColor1');
27+
padding: 5px;
28+
}
29+
::v-deep(a) {
30+
color: v-bind('themeVars.textColor1');
31+
}
32+
</style>

src/tools/jq-tester/jq-tester.vue

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,27 @@ const jsonValidation = useValidation({
5454
mb-2
5555
/>
5656

57-
<n-radio-group v-model:value="jqtype" name="jqtype">
58-
<n-space>
59-
<n-radio
60-
v-for="type in jqtypes"
61-
:key="type.value"
62-
:value="type.value"
63-
:label="type.label"
64-
/>
65-
</n-space>
66-
</n-radio-group>
57+
<div mb-2 flex justify-center>
58+
<n-radio-group v-model:value="jqtype" name="jqtype">
59+
<n-space>
60+
<n-radio
61+
v-for="type in jqtypes"
62+
:key="type.value"
63+
:value="type.value"
64+
:label="type.label"
65+
/>
66+
</n-space>
67+
</n-radio-group>
68+
</div>
69+
70+
<div mb-2 flex justify-center>
71+
<router-link v-if="jqtype === 'jq'" target="_blank" to="/jq-memo" mb-1 mt-1>
72+
See <code>jq</code> Cheatsheet
73+
</router-link>
74+
<router-link v-if="jqtype === 'jsonpath'" target="_blank" to="/jsonpath-memo" mb-1 mt-1>
75+
See JSONPath Cheatsheet
76+
</router-link>
77+
</div>
6778

6879
<c-input-text
6980
v-model:value="json"

src/tools/jsonpath-memo/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Brackets } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'JSONPath Syntax Cheatsheet',
6+
path: '/jsonpath-memo',
7+
description: 'JSONPath Syntax Cheatsheet',
8+
keywords: ['jsonpath', 'cheatsheet', 'memo'],
9+
component: () => import('./jsonpath-memo.vue'),
10+
icon: Brackets,
11+
createdAt: new Date('2024-08-15'),
12+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
## Syntax
2+
3+
Depending on the client used JSONPath expressions do start with `$.` indicating the root element.
4+
Some clients omit the leading `$.`.
5+
6+
| Syntax | Description |
7+
| ------ | :--------- |
8+
| `$.store.book[0].title` | |
9+
| `store.book[0].title` | With implicit `$.` |
10+
| `$['store']['book'][0]['title']` | Alternative notation similar to scripting languages |
11+
12+
## Tree Traversal
13+
14+
| Syntax | Description |
15+
| ------ | :--------- |
16+
| `$.parentNode.childNode.field` | XPath: `/parentNode/childNode/@field` (content of "field" of all "childNode"s of "parentNode") |
17+
| `$..anyChildNode` | XPath: `//anyChildNode` (all children at any depth named "anyChildNode") |
18+
| `$.parentNode.*` | XPath: `/parentNode/*` (all children below) |
19+
20+
## Array Access
21+
22+
| Syntax | Description |
23+
| ------ | :--------- |
24+
| `$.myList[0]` | first element |
25+
| `$.myList[-1]` | last element |
26+
| `$.myList[2:3]` | range |
27+
| `$.myList[0,4,5]` | selection |
28+
29+
## Filtering
30+
31+
| Syntax | Description |
32+
| ------ | :--------- |
33+
| `$.customer[?(@.car)]` | Only "customer"s that have attribute "car" |
34+
| `$.customer[?(@.car == 'Ford Fiesta')]` | Only "customer"s with "Ford Fiesta"s |
35+
| `$.customer[?(@.age > 18)]` | Only adults |
36+
37+
## Complex Conditions
38+
39+
| Syntax | Description |
40+
| ------ | :--------- |
41+
| `$.customer[?(@.age > 18 \|\| @.car == 'Ford Fiesta')]` | logical or |
42+
| `$.customer[?(@.age < 18 && @.hobby == 'Biking' )]` | logical and |
43+
44+
## Output Mapping
45+
46+
| Syntax | Description |
47+
| ------ | :--------- |
48+
| `$.[].{Name:name, Age:age, Hobbies:details.hobbies}` | Mapping fields/nested fields to new set
49+
50+
## Credits
51+
52+
Original author: https://gist.github.com/mackoj/5786f8b95da0a82e8e003f444c4295bf
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<script setup lang="ts">
2+
import { useThemeVars } from 'naive-ui';
3+
import Memo from './jsonpath-memo.md';
4+
5+
const themeVars = useThemeVars();
6+
</script>
7+
8+
<template>
9+
<div max-w-600px>
10+
<Memo style="overflow-x: auto;" />
11+
</div>
12+
</template>
13+
14+
<style lang="less" scoped>
15+
::v-deep(pre) {
16+
margin: 0;
17+
padding: 15px 22px;
18+
background-color: v-bind('themeVars.cardColor');
19+
border-radius: 4px;
20+
overflow: auto;
21+
}
22+
::v-deep(table) {
23+
border-collapse: collapse;
24+
}
25+
::v-deep(table), ::v-deep(td), ::v-deep(th) {
26+
border: 1px solid v-bind('themeVars.textColor1');
27+
padding: 5px;
28+
}
29+
::v-deep(a) {
30+
color: v-bind('themeVars.textColor1');
31+
}
32+
</style>

0 commit comments

Comments
 (0)