Skip to content

Commit 62a54be

Browse files
authored
Merge pull request #13 from step-/issue-12
Callback interface for embedding JSON.awk
2 parents 4aa41b3 + b551c16 commit 62a54be

File tree

7 files changed

+406
-198
lines changed

7 files changed

+406
-198
lines changed

FAQ.md

Lines changed: 0 additions & 159 deletions
This file was deleted.

JSON.awk

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/usr/bin/awk -f
22
#
33
# Software: JSON.awk - a practical JSON parser written in awk
4-
# Version: 1.12
5-
# Author: step- on github.com
4+
# Version: 1.2
5+
# Author: user step- on GitHub.com
66
# License: This software is licensed under the MIT or the Apache 2 license.
77
# Project home: https://github.com/step-/JSON.awk.git
88
# Credits: This software includes major portions of JSON.sh, a pipeable JSON
@@ -16,8 +16,8 @@
1616
# printf "%s\n" Filepath [Filepath...] | awk [-v Option="value"...] -f JSON.awk
1717
# Options: (default value in braces)
1818
# BRIEF=: 0 or 1 when 1 don't print non-leaf nodes {1}
19-
# STREAM=: 0 or 1 when 0 store jpaths in JPATHS[] for stub function apply() {1}
20-
# Setting STREAM=0 is intended for custom applications that rewrite function apply().
19+
# STREAM=: 0 or 1 when 0 don't output and call externally-defined callbacks.
20+
# Setting STREAM=0 is intended for custom applications that embed JSON.awk.
2121

2222
BEGIN { #{{{
2323
if (BRIEF == "") BRIEF=1 # when 1 parse() omits printing non-leaf nodes
@@ -48,31 +48,22 @@ BEGIN { #{{{
4848
reset() # See important application note in reset()
4949

5050
tokenize($0) # while(get_token()) {print TOKEN}
51-
if (0 == parse()) {
52-
apply(JPATHS, NJPATHS)
51+
if (0 == parse() && 0 == STREAM) {
52+
# Call back the embedding program passing an array of jpaths.
53+
cb_jpaths(JPATHS, NJPATHS)
5354
}
5455
}
5556
#}}}
5657

5758
END { # process invalid files {{{
58-
for(name in FAILS) {
59-
print "invalid: " name
60-
print FAILS[name]
59+
if (0 == STREAM) {
60+
# Call back the embedding program passing an associative array
61+
# of failed objects.
62+
cb_fails(FAILS, NFAILS)
6163
}
6264
}
6365
#}}}
6466

65-
# Function apply is a stub reserved for custom applications. It matters only
66-
# when STREAM=0. In its default form below apply() simply replicates JSON.sh's
67-
# output mode. JSON.sh prints in function parse() when STREAM=1 only. Default
68-
# stub function apply() prints below when STREAM=0 only because then (and only
69-
# then) size can be > 0.
70-
function apply (ary, size, i) { # stub {{{
71-
for (i=1; i <= size; i++)
72-
print ary[i]
73-
}
74-
#}}}
75-
7667
function get_token() { #{{{
7768
# usage: {tokenize($0); while(get_token()) {print TOKEN}}
7869

@@ -235,9 +226,18 @@ function reset() { #{{{
235226
#}}}
236227

237228
function scream(msg) { #{{{
229+
NFAILS += (FILENAME in FAILS ? 0 : 1)
238230
FAILS[FILENAME] = FAILS[FILENAME] (FAILS[FILENAME]!="" ? "\n" : "") msg
239-
msg = FILENAME ": " msg
240-
print msg >"/dev/stderr"
231+
if(0 == STREAM) {
232+
# Call back the embedding program passing the error message,
233+
# which will be printed to stderr if the callback returns non-zero.
234+
if(cb_fail1(msg)) {
235+
print FILENAME ": " msg >"/dev/stderr"
236+
}
237+
} else {
238+
# Print error message when not not embedded.
239+
print FILENAME ": " msg >"/dev/stderr"
240+
}
241241
}
242242
#}}}
243243

README.md

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ JSON.awk
33

44
A practical JSON parser written in awk.
55

6-
Quick Start
7-
-----------
6+
Introduction
7+
------------
88

99
JSON.awk is a self-contained, single-file program with no external dependencies.
1010
It is similar to [JSON.sh](https://github.com/dominictarr/JSON.sh), a JSON
@@ -15,51 +15,57 @@ will not find all of JSON.sh features in JSON.awk, and viceversa.
1515
Features
1616
--------
1717

18+
* Single file without external dependencies
1819
* JSON.sh compatible output format (as of 2013-03-13)
19-
* Can parse one or multiple input files in a single invocation
20-
* Captures invalid JSON input and processes it on exit
21-
* Written for awk; does not require gawk extensions;
22-
works with mawk 1.3.4 20150503 and higher [&raquo;6](https://github.com/step-/JSON.awk/issues/6);
23-
* Single file, does not depend on external programs
24-
* Your choice of MIT or Apache 2 license
20+
* Can parse one or multiple input files within a single invocation
21+
* Can be embedded in other awk programs
22+
* Invalid JSON input is captured and can be processed on exit
23+
* Written for POSIX awk; does not require GNU gawk extensions;
24+
works with mawk 1.3.4 20150503 and higher
25+
* Choice of MIT or Apache 2 license
2526

2627
Supported Platforms
2728
-------------------
2829

29-
All OS platforms where a modern implementation of awk is available. Special cases:
30+
All OS platforms where a POSIX awk implementation is available. Special cases:
3031

3132
* FreeBSD [&raquo;10](https://github.com/step-/JSON.awk/issues/10)
3233

3334
Setup
3435
-----
3536

36-
Just drop the file JSON.awk in your project folder and run it as an awk
37-
script.
37+
Drop file JSON.awk in your project folder and follow the examples.
3838

3939
Usage Examples
4040
--------------
4141

42-
For full usage instructions and command-line options please read [FAQ 1](FAQ.md).
42+
For full instructions please [read the docs](doc/usage.md).
43+
If you use mawk please read [FAQ 6](FAQ.md#6).
4344

4445
Passing file names as command arguments:
4546

4647
```sh
47-
awk -f JSON.awk file1.json file2.json...
48+
awk -f JSON.awk file1.json [file2.json...]
4849

4950
awk -f JSON.awk - < file.json
5051

5152
cat file.json | awk -f JSON.awk -
5253
```
5354

5455
Passing file names on stdin:
55-
```sh
56-
echo -e "file1.json\nfile2.json" > filenames && awk -f JSON.awk < filenames
5756

57+
```sh
5858
echo -e "file1.json\nfile2.json" | awk -f JSON.awk
5959
```
6060

61-
Projects that use JSON.awk
62-
--------------------------
61+
Embedded in another awk program ([FAQ 5](FAQ.md#5)):
62+
63+
```
64+
awk -f your-callbacks.awk -f JSON.awk file.json
65+
```
66+
67+
Projects known to use JSON.awk
68+
------------------------------
6369

6470
* [KindleLauncher](https://bitbucket.org/ixtab/kindlelauncher/overview)
6571
a.k.a. KUAL, an application launcher for the Kindle e-ink models, uses

callbacks.awk

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Callbacks reserved for awk programs that embed JSON.awk.
2+
# Mawk must always define all callbacks, see note #2 of doc/embed.md.
3+
# Gawk and busybox awk must define callbacks when STREAM=1 only.
4+
# For callback purpose, see FAQ.md#5.
5+
6+
# cb_jpaths - call back for processing jpath
7+
# Called in JSON.awk's main loop when STREAM=0 only.
8+
# This example illustrates printing jpaths to stdout,
9+
# much like JSON.awk does when STREAM=1.
10+
function cb_jpaths (ary, size, i) {
11+
12+
# Print ary - array of size jpaths.
13+
for(i=1; i <= size; i++) {
14+
print "cb_jpaths", ary[i]
15+
}
16+
}
17+
18+
# cb_fails - call back for processing all error messages at once after parsing
19+
# has completed. Called in JSON.awk's END action when STREAM=0 only.
20+
# This example illustrates printing parsing errors to stdout,
21+
function cb_fails (ary, size, k) {
22+
23+
# Print ary - associative array of parsing failures.
24+
# ary's keys are the size input file names that JSON.awk read.
25+
for(k in ary) {
26+
print "cb_fails: invalid input file:", k
27+
print FAILS[k]
28+
}
29+
}
30+
31+
# cb_fail1 - call back for processing a single parse error as soon as it is
32+
# encountered. Called in JSON.awk's main loop when STREAM=0 only.
33+
# Return non-zero to let JSON.awk also print the message to stderr.
34+
# This example illustrates printing the error message to stdout only.
35+
function cb_fail1 (message) {
36+
37+
print "cb_fail1: invalid input file:", FILENAME
38+
print message
39+
}
40+

0 commit comments

Comments
 (0)