-
Notifications
You must be signed in to change notification settings - Fork 1
/
jsonf.go
107 lines (96 loc) · 2.68 KB
/
jsonf.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"log"
"os"
"strconv"
)
func main() {
defer func() {
if r := recover(); r != nil {
log.Fatalln(r)
}
}()
var opts JsonfOptions
HandleArgs(&opts)
Jsonf(opts)
}
type JsonfOptions struct {
decoder *json.Decoder
output io.Writer
keyWrap string
arrWrap string
seperator string
includeKeys bool
}
func HandleArgs(opts *JsonfOptions) {
var inputFile string
flag.StringVar(&inputFile, "i", "", "The input file. Defaults to stdin.")
var outputFile string
flag.StringVar(&outputFile, "o", "", "The output file. Defaults to stdout.")
flag.StringVar(&opts.keyWrap, "k", "{}", "The runes used to wrap output keys.")
flag.StringVar(&opts.arrWrap, "a", "[]", "The runes used to wrap output array indexes.")
flag.StringVar(&opts.seperator, "sep", ">", "String used to seperate keys.")
flag.BoolVar(&opts.includeKeys, "keys", false, "If true, keys are printed on their own line.")
flag.Parse()
if len(inputFile) == 0 {
opts.decoder = json.NewDecoder(os.Stdin)
} else if input, err := os.Open(inputFile); err == nil {
opts.decoder = json.NewDecoder(input)
} else {
panic(err)
}
if len(outputFile) == 0 {
opts.output = os.Stdout
} else if output, err := os.Open(outputFile); err == nil {
opts.output = output
} else {
panic(err)
}
if len(opts.keyWrap) != 2 {
panic("-k must contain exactly two characters")
}
if len(opts.arrWrap) != 2 {
panic("-a must contain exactly two characters")
}
}
func Jsonf(opts JsonfOptions) {
for numReads := 0; ; numReads++ {
var json interface{}
if err := opts.decoder.Decode(&json); err != nil {
if err.Error() != "EOF" {
panic(err)
} else {
return
}
}
ProcessJsonValue(opts, strconv.Itoa(numReads), json)
}
}
func ProcessJsonValue(opts JsonfOptions, leadKey string, json interface{}) {
switch json.(type) {
case map[string]interface{}:
for key, value := range json.(map[string]interface{}) {
keyLead := fmt.Sprintf("%s%s%c%s%c", leadKey, opts.seperator, opts.keyWrap[0], key, opts.keyWrap[1])
if opts.includeKeys {
fmt.Fprintln(opts.output, keyLead)
}
ProcessJsonValue(opts, keyLead, value)
}
case []interface{}:
if opts.includeKeys {
fmt.Fprintf(opts.output, "%s%s%c%c\n", leadKey, opts.seperator, opts.arrWrap[0], opts.arrWrap[1])
}
for index, value := range json.([]interface{}) {
elemLead := fmt.Sprintf("%s%s%c%d%c", leadKey, opts.seperator, opts.arrWrap[0], index, opts.arrWrap[1])
ProcessJsonValue(opts, elemLead, value)
}
case string:
fmt.Fprintf(opts.output, "%s%s%s\n", leadKey, opts.seperator, strconv.Quote(json.(string)))
default:
fmt.Fprintf(opts.output, "%s%s%v\n", leadKey, opts.seperator, json)
}
}