csonpath 0.15.0__tar.gz → 0.17.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {csonpath-0.15.0 → csonpath-0.17.0}/Makefile +22 -4
- {csonpath-0.15.0/csonpath.egg-info → csonpath-0.17.0}/PKG-INFO +100 -3
- {csonpath-0.15.0 → csonpath-0.17.0}/README.md +99 -2
- {csonpath-0.15.0 → csonpath-0.17.0}/configure +5 -0
- {csonpath-0.15.0 → csonpath-0.17.0/csonpath.egg-info}/PKG-INFO +100 -3
- {csonpath-0.15.0 → csonpath-0.17.0}/csonpath.egg-info/SOURCES.txt +1 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/csonpath.h +133 -69
- {csonpath-0.15.0 → csonpath-0.17.0}/csonpath_do.h +9 -9
- {csonpath-0.15.0 → csonpath-0.17.0}/csonpath_json-c.h +21 -9
- csonpath-0.17.0/csonpath_my_fuzzing.h +440 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/csonpath_python.c +168 -30
- {csonpath-0.15.0 → csonpath-0.17.0}/csonpath_yyjson.h +5 -3
- {csonpath-0.15.0 → csonpath-0.17.0}/pyproject.toml +2 -2
- {csonpath-0.15.0 → csonpath-0.17.0}/LICENSE +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/MANIFEST.in +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/csonpath.egg-info/dependency_links.txt +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/csonpath.egg-info/requires.txt +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/csonpath.egg-info/top_level.txt +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/setup.cfg +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/setup.py +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/.git +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/.github/workflows/c-cpp.yml +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/.gitignore +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/LICENSE +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/Makefile +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/README.md +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/clib.json +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/formal_verification.md +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/re.c +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/re.h +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/scripts/exrex.py +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/scripts/regex_test.py +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/scripts/regex_test_neg.py +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/tests/test1.c +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/tests/test2.c +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/tests/test3.c +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/tests/test_compile.c +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/tests/test_print.c +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/tests/test_rand.c +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/tests/test_rand_neg.c +0 -0
- {csonpath-0.15.0 → csonpath-0.17.0}/tiny-regex-c/tests/test_thread.c +0 -0
|
@@ -5,7 +5,7 @@ YYJSON_LDFLAGS=$(shell pkg-config --libs yyjson)
|
|
|
5
5
|
|
|
6
6
|
include config.mk
|
|
7
7
|
|
|
8
|
-
all: test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union
|
|
8
|
+
all: test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union test-json-audit-bugs test-json-crash-vectors test-json-my-fuzz
|
|
9
9
|
|
|
10
10
|
YYJSON_TESTS=test-yyjson
|
|
11
11
|
|
|
@@ -15,7 +15,7 @@ bench:
|
|
|
15
15
|
bench-clean:
|
|
16
16
|
make -C bench clean
|
|
17
17
|
|
|
18
|
-
.PHONY: all clean tests pip-dev pip-dev bench bench-clean
|
|
18
|
+
.PHONY: all clean tests pip-dev pip-dev bench bench-clean tests-cli
|
|
19
19
|
|
|
20
20
|
CFLAGS+= -Wall -Wextra -Wno-unused-function -Wno-unused-parameter -O0 -g
|
|
21
21
|
|
|
@@ -43,10 +43,19 @@ test-json-get-array-big-index: tests/json-c/get-array-big-index.c csonpath_json-
|
|
|
43
43
|
test-json-union: tests/json-c/union.c csonpath_json-c.h csonpath.h csonpath_do.h
|
|
44
44
|
$(CC) tests/json-c/union.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-union $(JSON_C_LDFLAGS) $(LDFLAGS)
|
|
45
45
|
|
|
46
|
+
test-json-audit-bugs: tests/json-c/audit-bugs.c csonpath_json-c.h csonpath.h csonpath_do.h
|
|
47
|
+
$(CC) tests/json-c/audit-bugs.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-audit-bugs $(JSON_C_LDFLAGS) $(LDFLAGS)
|
|
48
|
+
|
|
49
|
+
test-json-crash-vectors: tests/json-c/crash-vectors.c csonpath_json-c.h csonpath.h csonpath_do.h
|
|
50
|
+
$(CC) tests/json-c/crash-vectors.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-crash-vectors $(JSON_C_LDFLAGS) $(LDFLAGS)
|
|
51
|
+
|
|
52
|
+
test-json-my-fuzz: tests/json-c/my_fuzz.c csonpath_json-c.h csonpath_my_fuzzing.h csonpath.h csonpath_do.h
|
|
53
|
+
$(CC) tests/json-c/my_fuzz.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-json-my-fuzz $(JSON_C_LDFLAGS) $(LDFLAGS)
|
|
54
|
+
|
|
46
55
|
test-yyjson: tests/yyjson/test-yyjson.c csonpath_yyjson.h csonpath.h csonpath_do.h
|
|
47
56
|
$(CC) tests/yyjson/test-yyjson.c $(EXTRA_FILES) $(YYJSON_CFLAGS) $(CFLAGS) -Wno-format -I./ -o test-yyjson $(YYJSON_LDFLAGS) $(LDFLAGS)
|
|
48
57
|
|
|
49
|
-
|
|
58
|
+
tests-c: test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union test-json-audit-bugs test-json-crash-vectors test-yyjson test-json-my-fuzz
|
|
50
59
|
./test-json-c-get-a
|
|
51
60
|
./test-json-update
|
|
52
61
|
./test-json-filter
|
|
@@ -55,7 +64,16 @@ test-yyjson: tests/yyjson/test-yyjson.c csonpath_yyjson.h csonpath.h csonpath_do
|
|
|
55
64
|
./test-json-filter-and-missing-key
|
|
56
65
|
./test-json-get-array-big-index
|
|
57
66
|
./test-json-union
|
|
67
|
+
./test-json-audit-bugs
|
|
68
|
+
./test-json-crash-vectors
|
|
58
69
|
./test-yyjson
|
|
70
|
+
./test-json-my-fuzz
|
|
71
|
+
|
|
72
|
+
csonpath: cli/csonpath_cli.c csonpath_json-c.h csonpath.h csonpath_do.h
|
|
73
|
+
$(CC) cli/csonpath_cli.c $(EXTRA_FILES) $(JSON_C_CFLAGS) $(CFLAGS) -I./ -o csonpath $(JSON_C_LDFLAGS) $(LDFLAGS)
|
|
74
|
+
|
|
75
|
+
tests-cli: csonpath
|
|
76
|
+
bash tests/cli/run.sh
|
|
59
77
|
|
|
60
78
|
pip-dev:
|
|
61
79
|
pip install -e .[dev] --force-reinstall
|
|
@@ -66,5 +84,5 @@ tests-py: pip-dev
|
|
|
66
84
|
tests: tests-py tests-c
|
|
67
85
|
|
|
68
86
|
clean:
|
|
69
|
-
rm -rvf test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union test-yyjson
|
|
87
|
+
rm -rvf test-json-c-get-a test-json-update test-json-filter test-json-subpath test-json-c-array-root test-json-filter-and-missing-key test-json-get-array-big-index test-json-union test-json-audit-bugs test-json-crash-vectors test-yyjson test-json-my-fuzz csonpath
|
|
70
88
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csonpath
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
4
4
|
Description-Content-Type: text/markdown
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Provides-Extra: dev
|
|
@@ -15,7 +15,7 @@ Dynamic: license-file
|
|
|
15
15
|
|
|
16
16
|
**csonpath** is a partial [JSONPath](https://goessner.net/articles/JsonPath/) implementation in C, with Python bindings. It allows you to query, update, and remove data from JSON objects using path expressions.
|
|
17
17
|
|
|
18
|
-
Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work with any C library or environment that manipulates array, object, and scalar types—not just JSON. Out of the box, backends for [json-c](https://github.com/json-c/json-c)
|
|
18
|
+
Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work with any C library or environment that manipulates array, object, and scalar types—not just JSON. Out of the box, backends for [json-c](https://github.com/json-c/json-c), [yyjson](https://github.com/ibireme/yyjson), Python and Rust (via `serde_json`) are provided.
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
@@ -30,7 +30,8 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
|
|
|
30
30
|
| Array index | `$.array[0]` | Access by zero-based index |
|
|
31
31
|
| Wildcard `[*]` | `$.array[*].field` | Iterate all array elements |
|
|
32
32
|
| Recursive descent `..` | `$..name` | Search recursively for a key |
|
|
33
|
-
| Union
|
|
33
|
+
| Union `,` (inside brackets) | `$['a','b']`, `$.array[0,1]`, `$.items[?n==1, ?n==2]` | Match all listed selectors at once |
|
|
34
|
+
| OR fallback `\|` | `$.a \| $.b` | Try the left path first; fall back to the right one if it does not match. Only the first successful path is used. |
|
|
34
35
|
| Filters | `$.items[?price > 10]` | Filter array elements |
|
|
35
36
|
| Regex filters | `$.items[?name =~ "foo"]` | POSIX regex-based filtering |
|
|
36
37
|
| Multiple filters (`&`) | `$.items[?a=1 & b=2]` | Combine conditions |
|
|
@@ -61,6 +62,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
|
|
|
61
62
|
- [Usage](#-usage)
|
|
62
63
|
- [C API Reference](#-c-api-reference)
|
|
63
64
|
- [Python API Reference](#-python-api-reference)
|
|
65
|
+
- [CLI](#%EF%B8%8F-cli)
|
|
64
66
|
- [Custom Backends](#-custom-backends)
|
|
65
67
|
- [Running Tests](#-running-tests)
|
|
66
68
|
- [Directory Structure](#-directory-structure)
|
|
@@ -86,6 +88,20 @@ Make sure to link against `json-c` when compiling:
|
|
|
86
88
|
gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
|
|
87
89
|
```
|
|
88
90
|
|
|
91
|
+
### C (Rust backend)
|
|
92
|
+
The Rust backend is located in `rust/`. It builds both a safe Rust API and the C glue required by the csonpath core.
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
cd rust
|
|
96
|
+
cargo build
|
|
97
|
+
cargo test
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
To use it from C, include the backend header and link against the produced static library:
|
|
101
|
+
```c
|
|
102
|
+
#include "rust/csonpath_rust_backend.h"
|
|
103
|
+
```
|
|
104
|
+
|
|
89
105
|
### Python
|
|
90
106
|
Install from PyPI:
|
|
91
107
|
```sh
|
|
@@ -251,6 +267,76 @@ Free the csonpath object.
|
|
|
251
267
|
|
|
252
268
|
---
|
|
253
269
|
|
|
270
|
+
## 🖥️ CLI
|
|
271
|
+
|
|
272
|
+
A standalone C CLI is available in `cli/csonpath_cli.c`. It links directly against `json-c` and the csonpath C core, so it works without Python.
|
|
273
|
+
|
|
274
|
+
```sh
|
|
275
|
+
make csonpath # build ./csonpath
|
|
276
|
+
make tests-cli # run shell tests
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
It reads JSON from stdin, a file (`-f`), or a string (`-s`) and exposes the library operations through action flags.
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
# Get the first match (default)
|
|
283
|
+
echo '{"a": "value", "array": [1, 2, 3]}' | ./csonpath '$.a'
|
|
284
|
+
# => "value"
|
|
285
|
+
|
|
286
|
+
# Find all matches
|
|
287
|
+
echo '{"items": [{"price": 5}, {"price": 15}]}' | ./csonpath -a '$.items[?price > 10]'
|
|
288
|
+
# => [{"price":15}]
|
|
289
|
+
|
|
290
|
+
# One match per line
|
|
291
|
+
echo '{"array": [1, 2, 3]}' | ./csonpath -a -o lines '$.array[*]'
|
|
292
|
+
# => 1
|
|
293
|
+
# => 2
|
|
294
|
+
# => 3
|
|
295
|
+
|
|
296
|
+
# Set or create a value
|
|
297
|
+
echo '{"a": 1}' | ./csonpath --set '42' '$.x.y.z'
|
|
298
|
+
# => {"a":1,"x":{"y":{"z":42}}}
|
|
299
|
+
|
|
300
|
+
# Or with a positional value
|
|
301
|
+
echo '{"a": 1}' | ./csonpath '$.x.y.z' '42'
|
|
302
|
+
|
|
303
|
+
# Remove matches
|
|
304
|
+
echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
|
|
305
|
+
# => {"a":1}
|
|
306
|
+
|
|
307
|
+
# Edit a file in place
|
|
308
|
+
./csonpath -f data.json -p -i --set '"2.0"' '$.version'
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Options
|
|
312
|
+
|
|
313
|
+
| Option | Description |
|
|
314
|
+
|---|---|
|
|
315
|
+
| `-a`, `--all` | Return all matches instead of the first one. |
|
|
316
|
+
| `-d`, `--delete` | Remove matches and print the modified JSON. |
|
|
317
|
+
| `--set VALUE` | Set `PATH` to `VALUE` (JSON). |
|
|
318
|
+
| `VALUE` (positional) | Alternative to `--set`. |
|
|
319
|
+
| `-r`, `--raw` | Treat the value as a raw string. |
|
|
320
|
+
| `-i`, `--in-place` | Edit `FILE` in place (requires `--file`). |
|
|
321
|
+
| `--strict` | Exit with an error if `--delete` removes nothing. |
|
|
322
|
+
| `-f FILE`, `--file FILE` | Read JSON from `FILE` instead of stdin. |
|
|
323
|
+
| `-s JSON`, `--string JSON` | Read JSON from a string. |
|
|
324
|
+
| `-j`, `--jq-like` | Allow jq-style paths without a leading `$`. |
|
|
325
|
+
| `-p`, `--pretty` | Pretty-print JSON output. |
|
|
326
|
+
| `-o {json,pretty,raw,lines}` | Output format (default: `json`). |
|
|
327
|
+
| `-e`, `--empty-array` | Return `[]` instead of nothing when `-a` matches nothing. |
|
|
328
|
+
|
|
329
|
+
### Exit codes
|
|
330
|
+
|
|
331
|
+
| Code | Meaning |
|
|
332
|
+
|---|---|
|
|
333
|
+
| `0` | Success. |
|
|
334
|
+
| `1` | No match found, or `--strict` delete found nothing. |
|
|
335
|
+
| `EINVAL` | Usage error, JSON parse error, JSONPath compilation error, or invalid JSON value. |
|
|
336
|
+
| `errno` | I/O error (e.g. `ENOENT`, `EACCES`). |
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
254
340
|
## 🔌 Custom Backends
|
|
255
341
|
|
|
256
342
|
csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
|
|
@@ -259,7 +345,9 @@ To create a custom backend, define the required macros and types in a header fil
|
|
|
259
345
|
|
|
260
346
|
For more details, see the existing backend implementations:
|
|
261
347
|
- `csonpath_json-c.h` — json-c backend
|
|
348
|
+
- `csonpath_yyjson.h` — yyjson backend
|
|
262
349
|
- `csonpath_python.c` — Python backend
|
|
350
|
+
- `rust/csonpath_rust_backend.h` — Rust / serde_json backend
|
|
263
351
|
|
|
264
352
|
---
|
|
265
353
|
|
|
@@ -270,6 +358,12 @@ For more details, see the existing backend implementations:
|
|
|
270
358
|
make tests-c
|
|
271
359
|
```
|
|
272
360
|
|
|
361
|
+
### Rust Tests
|
|
362
|
+
```sh
|
|
363
|
+
cd rust
|
|
364
|
+
cargo test
|
|
365
|
+
```
|
|
366
|
+
|
|
273
367
|
### Python Tests
|
|
274
368
|
```sh
|
|
275
369
|
make tests-py
|
|
@@ -288,7 +382,10 @@ make tests
|
|
|
288
382
|
|---|---|
|
|
289
383
|
| `csonpath.h`, `csonpath_do.h` | Core implementation (header-only style) |
|
|
290
384
|
| `csonpath_json-c.h` | json-c backend |
|
|
385
|
+
| `csonpath_yyjson.h` | yyjson backend |
|
|
291
386
|
| `csonpath_python.c` | Python C extension backend |
|
|
387
|
+
| `rust/` | Rust backend (safe API, FFI, C glue) |
|
|
388
|
+
| `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
|
|
292
389
|
| `tests/` | C and Python test suites |
|
|
293
390
|
| `bench/` | Performance benchmarks |
|
|
294
391
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
**csonpath** is a partial [JSONPath](https://goessner.net/articles/JsonPath/) implementation in C, with Python bindings. It allows you to query, update, and remove data from JSON objects using path expressions.
|
|
8
8
|
|
|
9
|
-
Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work with any C library or environment that manipulates array, object, and scalar types—not just JSON. Out of the box, backends for [json-c](https://github.com/json-c/json-c)
|
|
9
|
+
Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work with any C library or environment that manipulates array, object, and scalar types—not just JSON. Out of the box, backends for [json-c](https://github.com/json-c/json-c), [yyjson](https://github.com/ibireme/yyjson), Python and Rust (via `serde_json`) are provided.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -21,7 +21,8 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
|
|
|
21
21
|
| Array index | `$.array[0]` | Access by zero-based index |
|
|
22
22
|
| Wildcard `[*]` | `$.array[*].field` | Iterate all array elements |
|
|
23
23
|
| Recursive descent `..` | `$..name` | Search recursively for a key |
|
|
24
|
-
| Union
|
|
24
|
+
| Union `,` (inside brackets) | `$['a','b']`, `$.array[0,1]`, `$.items[?n==1, ?n==2]` | Match all listed selectors at once |
|
|
25
|
+
| OR fallback `\|` | `$.a \| $.b` | Try the left path first; fall back to the right one if it does not match. Only the first successful path is used. |
|
|
25
26
|
| Filters | `$.items[?price > 10]` | Filter array elements |
|
|
26
27
|
| Regex filters | `$.items[?name =~ "foo"]` | POSIX regex-based filtering |
|
|
27
28
|
| Multiple filters (`&`) | `$.items[?a=1 & b=2]` | Combine conditions |
|
|
@@ -52,6 +53,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
|
|
|
52
53
|
- [Usage](#-usage)
|
|
53
54
|
- [C API Reference](#-c-api-reference)
|
|
54
55
|
- [Python API Reference](#-python-api-reference)
|
|
56
|
+
- [CLI](#%EF%B8%8F-cli)
|
|
55
57
|
- [Custom Backends](#-custom-backends)
|
|
56
58
|
- [Running Tests](#-running-tests)
|
|
57
59
|
- [Directory Structure](#-directory-structure)
|
|
@@ -77,6 +79,20 @@ Make sure to link against `json-c` when compiling:
|
|
|
77
79
|
gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
|
|
78
80
|
```
|
|
79
81
|
|
|
82
|
+
### C (Rust backend)
|
|
83
|
+
The Rust backend is located in `rust/`. It builds both a safe Rust API and the C glue required by the csonpath core.
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
cd rust
|
|
87
|
+
cargo build
|
|
88
|
+
cargo test
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
To use it from C, include the backend header and link against the produced static library:
|
|
92
|
+
```c
|
|
93
|
+
#include "rust/csonpath_rust_backend.h"
|
|
94
|
+
```
|
|
95
|
+
|
|
80
96
|
### Python
|
|
81
97
|
Install from PyPI:
|
|
82
98
|
```sh
|
|
@@ -242,6 +258,76 @@ Free the csonpath object.
|
|
|
242
258
|
|
|
243
259
|
---
|
|
244
260
|
|
|
261
|
+
## 🖥️ CLI
|
|
262
|
+
|
|
263
|
+
A standalone C CLI is available in `cli/csonpath_cli.c`. It links directly against `json-c` and the csonpath C core, so it works without Python.
|
|
264
|
+
|
|
265
|
+
```sh
|
|
266
|
+
make csonpath # build ./csonpath
|
|
267
|
+
make tests-cli # run shell tests
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
It reads JSON from stdin, a file (`-f`), or a string (`-s`) and exposes the library operations through action flags.
|
|
271
|
+
|
|
272
|
+
```sh
|
|
273
|
+
# Get the first match (default)
|
|
274
|
+
echo '{"a": "value", "array": [1, 2, 3]}' | ./csonpath '$.a'
|
|
275
|
+
# => "value"
|
|
276
|
+
|
|
277
|
+
# Find all matches
|
|
278
|
+
echo '{"items": [{"price": 5}, {"price": 15}]}' | ./csonpath -a '$.items[?price > 10]'
|
|
279
|
+
# => [{"price":15}]
|
|
280
|
+
|
|
281
|
+
# One match per line
|
|
282
|
+
echo '{"array": [1, 2, 3]}' | ./csonpath -a -o lines '$.array[*]'
|
|
283
|
+
# => 1
|
|
284
|
+
# => 2
|
|
285
|
+
# => 3
|
|
286
|
+
|
|
287
|
+
# Set or create a value
|
|
288
|
+
echo '{"a": 1}' | ./csonpath --set '42' '$.x.y.z'
|
|
289
|
+
# => {"a":1,"x":{"y":{"z":42}}}
|
|
290
|
+
|
|
291
|
+
# Or with a positional value
|
|
292
|
+
echo '{"a": 1}' | ./csonpath '$.x.y.z' '42'
|
|
293
|
+
|
|
294
|
+
# Remove matches
|
|
295
|
+
echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
|
|
296
|
+
# => {"a":1}
|
|
297
|
+
|
|
298
|
+
# Edit a file in place
|
|
299
|
+
./csonpath -f data.json -p -i --set '"2.0"' '$.version'
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Options
|
|
303
|
+
|
|
304
|
+
| Option | Description |
|
|
305
|
+
|---|---|
|
|
306
|
+
| `-a`, `--all` | Return all matches instead of the first one. |
|
|
307
|
+
| `-d`, `--delete` | Remove matches and print the modified JSON. |
|
|
308
|
+
| `--set VALUE` | Set `PATH` to `VALUE` (JSON). |
|
|
309
|
+
| `VALUE` (positional) | Alternative to `--set`. |
|
|
310
|
+
| `-r`, `--raw` | Treat the value as a raw string. |
|
|
311
|
+
| `-i`, `--in-place` | Edit `FILE` in place (requires `--file`). |
|
|
312
|
+
| `--strict` | Exit with an error if `--delete` removes nothing. |
|
|
313
|
+
| `-f FILE`, `--file FILE` | Read JSON from `FILE` instead of stdin. |
|
|
314
|
+
| `-s JSON`, `--string JSON` | Read JSON from a string. |
|
|
315
|
+
| `-j`, `--jq-like` | Allow jq-style paths without a leading `$`. |
|
|
316
|
+
| `-p`, `--pretty` | Pretty-print JSON output. |
|
|
317
|
+
| `-o {json,pretty,raw,lines}` | Output format (default: `json`). |
|
|
318
|
+
| `-e`, `--empty-array` | Return `[]` instead of nothing when `-a` matches nothing. |
|
|
319
|
+
|
|
320
|
+
### Exit codes
|
|
321
|
+
|
|
322
|
+
| Code | Meaning |
|
|
323
|
+
|---|---|
|
|
324
|
+
| `0` | Success. |
|
|
325
|
+
| `1` | No match found, or `--strict` delete found nothing. |
|
|
326
|
+
| `EINVAL` | Usage error, JSON parse error, JSONPath compilation error, or invalid JSON value. |
|
|
327
|
+
| `errno` | I/O error (e.g. `ENOENT`, `EACCES`). |
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
245
331
|
## 🔌 Custom Backends
|
|
246
332
|
|
|
247
333
|
csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
|
|
@@ -250,7 +336,9 @@ To create a custom backend, define the required macros and types in a header fil
|
|
|
250
336
|
|
|
251
337
|
For more details, see the existing backend implementations:
|
|
252
338
|
- `csonpath_json-c.h` — json-c backend
|
|
339
|
+
- `csonpath_yyjson.h` — yyjson backend
|
|
253
340
|
- `csonpath_python.c` — Python backend
|
|
341
|
+
- `rust/csonpath_rust_backend.h` — Rust / serde_json backend
|
|
254
342
|
|
|
255
343
|
---
|
|
256
344
|
|
|
@@ -261,6 +349,12 @@ For more details, see the existing backend implementations:
|
|
|
261
349
|
make tests-c
|
|
262
350
|
```
|
|
263
351
|
|
|
352
|
+
### Rust Tests
|
|
353
|
+
```sh
|
|
354
|
+
cd rust
|
|
355
|
+
cargo test
|
|
356
|
+
```
|
|
357
|
+
|
|
264
358
|
### Python Tests
|
|
265
359
|
```sh
|
|
266
360
|
make tests-py
|
|
@@ -279,7 +373,10 @@ make tests
|
|
|
279
373
|
|---|---|
|
|
280
374
|
| `csonpath.h`, `csonpath_do.h` | Core implementation (header-only style) |
|
|
281
375
|
| `csonpath_json-c.h` | json-c backend |
|
|
376
|
+
| `csonpath_yyjson.h` | yyjson backend |
|
|
282
377
|
| `csonpath_python.c` | Python C extension backend |
|
|
378
|
+
| `rust/` | Rust backend (safe API, FFI, C glue) |
|
|
379
|
+
| `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
|
|
283
380
|
| `tests/` | C and Python test suites |
|
|
284
381
|
| `bench/` | Performance benchmarks |
|
|
285
382
|
|
|
@@ -21,12 +21,17 @@ for arg in $@; do
|
|
|
21
21
|
CFLAGS="${CFLAGS} -DCSONPATH_PCRE2_POSIX $(pkg-config --cflags libpcre2-posix)"
|
|
22
22
|
LDFLAGS="${LDFLAGS} $(pkg-config --libs libpcre2-posix)"
|
|
23
23
|
fi
|
|
24
|
+
if [ "--asan" = $arg ]; then
|
|
25
|
+
CFLAGS="${CFLAGS} -fsanitize=address -fno-omit-frame-pointer"
|
|
26
|
+
LDFLAGS="${LDFLAGS} -fsanitize=address"
|
|
27
|
+
fi
|
|
24
28
|
if [ "--help" = $arg ]; then
|
|
25
29
|
echo "help"
|
|
26
30
|
echo " --tiny-regex"
|
|
27
31
|
echo " --pcre2-regex"
|
|
28
32
|
echo " --pcre2-posix"
|
|
29
33
|
echo " --no-regex"
|
|
34
|
+
echo " --asan"
|
|
30
35
|
fi
|
|
31
36
|
done
|
|
32
37
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csonpath
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
4
4
|
Description-Content-Type: text/markdown
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Provides-Extra: dev
|
|
@@ -15,7 +15,7 @@ Dynamic: license-file
|
|
|
15
15
|
|
|
16
16
|
**csonpath** is a partial [JSONPath](https://goessner.net/articles/JsonPath/) implementation in C, with Python bindings. It allows you to query, update, and remove data from JSON objects using path expressions.
|
|
17
17
|
|
|
18
|
-
Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work with any C library or environment that manipulates array, object, and scalar types—not just JSON. Out of the box, backends for [json-c](https://github.com/json-c/json-c)
|
|
18
|
+
Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work with any C library or environment that manipulates array, object, and scalar types—not just JSON. Out of the box, backends for [json-c](https://github.com/json-c/json-c), [yyjson](https://github.com/ibireme/yyjson), Python and Rust (via `serde_json`) are provided.
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
@@ -30,7 +30,8 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
|
|
|
30
30
|
| Array index | `$.array[0]` | Access by zero-based index |
|
|
31
31
|
| Wildcard `[*]` | `$.array[*].field` | Iterate all array elements |
|
|
32
32
|
| Recursive descent `..` | `$..name` | Search recursively for a key |
|
|
33
|
-
| Union
|
|
33
|
+
| Union `,` (inside brackets) | `$['a','b']`, `$.array[0,1]`, `$.items[?n==1, ?n==2]` | Match all listed selectors at once |
|
|
34
|
+
| OR fallback `\|` | `$.a \| $.b` | Try the left path first; fall back to the right one if it does not match. Only the first successful path is used. |
|
|
34
35
|
| Filters | `$.items[?price > 10]` | Filter array elements |
|
|
35
36
|
| Regex filters | `$.items[?name =~ "foo"]` | POSIX regex-based filtering |
|
|
36
37
|
| Multiple filters (`&`) | `$.items[?a=1 & b=2]` | Combine conditions |
|
|
@@ -61,6 +62,7 @@ Unlike many JSONPath libraries, csonpath is **backend-agnostic**: it can work wi
|
|
|
61
62
|
- [Usage](#-usage)
|
|
62
63
|
- [C API Reference](#-c-api-reference)
|
|
63
64
|
- [Python API Reference](#-python-api-reference)
|
|
65
|
+
- [CLI](#%EF%B8%8F-cli)
|
|
64
66
|
- [Custom Backends](#-custom-backends)
|
|
65
67
|
- [Running Tests](#-running-tests)
|
|
66
68
|
- [Directory Structure](#-directory-structure)
|
|
@@ -86,6 +88,20 @@ Make sure to link against `json-c` when compiling:
|
|
|
86
88
|
gcc myapp.c -o myapp $(pkg-config --cflags --libs json-c)
|
|
87
89
|
```
|
|
88
90
|
|
|
91
|
+
### C (Rust backend)
|
|
92
|
+
The Rust backend is located in `rust/`. It builds both a safe Rust API and the C glue required by the csonpath core.
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
cd rust
|
|
96
|
+
cargo build
|
|
97
|
+
cargo test
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
To use it from C, include the backend header and link against the produced static library:
|
|
101
|
+
```c
|
|
102
|
+
#include "rust/csonpath_rust_backend.h"
|
|
103
|
+
```
|
|
104
|
+
|
|
89
105
|
### Python
|
|
90
106
|
Install from PyPI:
|
|
91
107
|
```sh
|
|
@@ -251,6 +267,76 @@ Free the csonpath object.
|
|
|
251
267
|
|
|
252
268
|
---
|
|
253
269
|
|
|
270
|
+
## 🖥️ CLI
|
|
271
|
+
|
|
272
|
+
A standalone C CLI is available in `cli/csonpath_cli.c`. It links directly against `json-c` and the csonpath C core, so it works without Python.
|
|
273
|
+
|
|
274
|
+
```sh
|
|
275
|
+
make csonpath # build ./csonpath
|
|
276
|
+
make tests-cli # run shell tests
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
It reads JSON from stdin, a file (`-f`), or a string (`-s`) and exposes the library operations through action flags.
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
# Get the first match (default)
|
|
283
|
+
echo '{"a": "value", "array": [1, 2, 3]}' | ./csonpath '$.a'
|
|
284
|
+
# => "value"
|
|
285
|
+
|
|
286
|
+
# Find all matches
|
|
287
|
+
echo '{"items": [{"price": 5}, {"price": 15}]}' | ./csonpath -a '$.items[?price > 10]'
|
|
288
|
+
# => [{"price":15}]
|
|
289
|
+
|
|
290
|
+
# One match per line
|
|
291
|
+
echo '{"array": [1, 2, 3]}' | ./csonpath -a -o lines '$.array[*]'
|
|
292
|
+
# => 1
|
|
293
|
+
# => 2
|
|
294
|
+
# => 3
|
|
295
|
+
|
|
296
|
+
# Set or create a value
|
|
297
|
+
echo '{"a": 1}' | ./csonpath --set '42' '$.x.y.z'
|
|
298
|
+
# => {"a":1,"x":{"y":{"z":42}}}
|
|
299
|
+
|
|
300
|
+
# Or with a positional value
|
|
301
|
+
echo '{"a": 1}' | ./csonpath '$.x.y.z' '42'
|
|
302
|
+
|
|
303
|
+
# Remove matches
|
|
304
|
+
echo '{"a": 1, "b": 2}' | ./csonpath -d '$.b'
|
|
305
|
+
# => {"a":1}
|
|
306
|
+
|
|
307
|
+
# Edit a file in place
|
|
308
|
+
./csonpath -f data.json -p -i --set '"2.0"' '$.version'
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Options
|
|
312
|
+
|
|
313
|
+
| Option | Description |
|
|
314
|
+
|---|---|
|
|
315
|
+
| `-a`, `--all` | Return all matches instead of the first one. |
|
|
316
|
+
| `-d`, `--delete` | Remove matches and print the modified JSON. |
|
|
317
|
+
| `--set VALUE` | Set `PATH` to `VALUE` (JSON). |
|
|
318
|
+
| `VALUE` (positional) | Alternative to `--set`. |
|
|
319
|
+
| `-r`, `--raw` | Treat the value as a raw string. |
|
|
320
|
+
| `-i`, `--in-place` | Edit `FILE` in place (requires `--file`). |
|
|
321
|
+
| `--strict` | Exit with an error if `--delete` removes nothing. |
|
|
322
|
+
| `-f FILE`, `--file FILE` | Read JSON from `FILE` instead of stdin. |
|
|
323
|
+
| `-s JSON`, `--string JSON` | Read JSON from a string. |
|
|
324
|
+
| `-j`, `--jq-like` | Allow jq-style paths without a leading `$`. |
|
|
325
|
+
| `-p`, `--pretty` | Pretty-print JSON output. |
|
|
326
|
+
| `-o {json,pretty,raw,lines}` | Output format (default: `json`). |
|
|
327
|
+
| `-e`, `--empty-array` | Return `[]` instead of nothing when `-a` matches nothing. |
|
|
328
|
+
|
|
329
|
+
### Exit codes
|
|
330
|
+
|
|
331
|
+
| Code | Meaning |
|
|
332
|
+
|---|---|
|
|
333
|
+
| `0` | Success. |
|
|
334
|
+
| `1` | No match found, or `--strict` delete found nothing. |
|
|
335
|
+
| `EINVAL` | Usage error, JSON parse error, JSONPath compilation error, or invalid JSON value. |
|
|
336
|
+
| `errno` | I/O error (e.g. `ENOENT`, `EACCES`). |
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
254
340
|
## 🔌 Custom Backends
|
|
255
341
|
|
|
256
342
|
csonpath is designed to be backend-agnostic. It can work with any data structure that supports array, object, and scalar semantics.
|
|
@@ -259,7 +345,9 @@ To create a custom backend, define the required macros and types in a header fil
|
|
|
259
345
|
|
|
260
346
|
For more details, see the existing backend implementations:
|
|
261
347
|
- `csonpath_json-c.h` — json-c backend
|
|
348
|
+
- `csonpath_yyjson.h` — yyjson backend
|
|
262
349
|
- `csonpath_python.c` — Python backend
|
|
350
|
+
- `rust/csonpath_rust_backend.h` — Rust / serde_json backend
|
|
263
351
|
|
|
264
352
|
---
|
|
265
353
|
|
|
@@ -270,6 +358,12 @@ For more details, see the existing backend implementations:
|
|
|
270
358
|
make tests-c
|
|
271
359
|
```
|
|
272
360
|
|
|
361
|
+
### Rust Tests
|
|
362
|
+
```sh
|
|
363
|
+
cd rust
|
|
364
|
+
cargo test
|
|
365
|
+
```
|
|
366
|
+
|
|
273
367
|
### Python Tests
|
|
274
368
|
```sh
|
|
275
369
|
make tests-py
|
|
@@ -288,7 +382,10 @@ make tests
|
|
|
288
382
|
|---|---|
|
|
289
383
|
| `csonpath.h`, `csonpath_do.h` | Core implementation (header-only style) |
|
|
290
384
|
| `csonpath_json-c.h` | json-c backend |
|
|
385
|
+
| `csonpath_yyjson.h` | yyjson backend |
|
|
291
386
|
| `csonpath_python.c` | Python C extension backend |
|
|
387
|
+
| `rust/` | Rust backend (safe API, FFI, C glue) |
|
|
388
|
+
| `csonpath_my_fuzzing.h` | Fuzzer helpers (C) |
|
|
292
389
|
| `tests/` | C and Python test suites |
|
|
293
390
|
| `bench/` | Performance benchmarks |
|
|
294
391
|
|