Skip to content

Commit b715e8e

Browse files
committed
updated jsonjoin docs and added support for -create and reading root object from stdin
1 parent 3113f92 commit b715e8e

File tree

3 files changed

+148
-38
lines changed

3 files changed

+148
-38
lines changed

cmds/jsonjoin/jsonjoin.go

+84-21
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,38 @@ import (
2222
)
2323

2424
var (
25-
usage = `USAGE: %s [OPTIONS] JSON_FILE_1 JSON_FILE_2`
25+
usage = `USAGE: %s [OPTIONS] JSON_FILE_1 [JSON_FILE_2 ...]`
2626

2727
description = `
2828
SYSNOPSIS
2929
30-
%s is a command line tool that takes two (or more) JSON object
31-
documents and combines into a new JSON object document based on
32-
the options chosen.
30+
%s is a command line tool that takes one (or more) JSON objects files
31+
and joins them to a root JSON object read from standard input (or
32+
file identified by -input option). By default the resulting
33+
joined JSON object is written to standard out.
34+
35+
The default behavior for %s is to create key/value pairs
36+
based on the joined JSON document names and their contents.
37+
This can be thought of as a branching behavior. Each additional
38+
file becomes a branch and its key/value pairs become leafs.
39+
The root JSON object is assumed to come from standard input
40+
but can be designated by the -input option or created by the
41+
-create option. Each additional file specified as a command line
42+
argument is then treated as a new branch.
43+
44+
In addition to the branching behavior you can join JSON objects in a
45+
flat manner. The flat joining process can be ether non-distructive
46+
adding new key/value pairs (-update option) or distructive
47+
overwriting key/value pairs (-overwrite option).
48+
49+
Note: %s doesn't support a JSON array as the root JSON object.
3350
`
3451

3552
examples = `
3653
EXAMPLES
3754
38-
Joining two JSON objects (maps)
55+
Consider two JSON objects one in person.json and another
56+
in profile.json.
3957
4058
person.json containes
4159
@@ -46,28 +64,47 @@ profile.json containes
4664
{ "name": "Doe, Jane", "bio": "World renowned geophysist.",
4765
"email": "[email protected]" }
4866
49-
A simple join of person.json with profile.json
67+
A simple join of person.json with profile.json (note the
68+
-create option)
5069
51-
%s person.json profile.json
70+
%s -create person.json profile.json
5271
53-
would yeild
72+
would yeild and object like
5473
5574
{
56-
"person": { "name": "Doe, Jane", "email":"[email protected]", "age": 42},
75+
"person": { "name": "Doe, Jane", "email":"[email protected]",
76+
"age": 42},
77+
"profile": { "name": "Doe, Jane", "bio": "World renowned geophysist.",
78+
"email": "[email protected]" }
79+
}
80+
81+
Likewise if you want to treat person.json as the root object and add
82+
profile.json as a branch try
83+
84+
cat person.json | %s profile.json
85+
86+
or
87+
88+
%s -i person.json profile.json
89+
90+
this yields an object like
91+
92+
{
93+
"name": "Doe, Jane", "email":"[email protected]", "age": 42,
5794
"profile": { "name": "Doe, Jane", "bio": "World renowned geophysist.",
5895
"email": "[email protected]" }
5996
}
6097
6198
You can modify this behavor with -update or -overwrite. Both options are
62-
order dependant (e.g. not associative, A update B does
99+
order dependant (i.e. not associative, A update B does
63100
not necessarily equal B update A).
64101
65102
+ -update will add unique key/values from the second object to the first object
66103
+ -overwrite replace key/values in first object one with second objects'
67104
68105
Running
69106
70-
%s -update person.json profile.json
107+
%s -create -update person.json profile.json
71108
72109
would yield
73110
@@ -76,7 +113,7 @@ would yield
76113
77114
Running
78115
79-
%s -update profile.json person.json
116+
%s -create -update profile.json person.json
80117
81118
would yield
82119
@@ -86,7 +123,7 @@ would yield
86123
87124
Running
88125
89-
%s -overwrite person.json profile.json
126+
%s -create -overwrite person.json profile.json
90127
91128
would yield
92129
@@ -98,11 +135,13 @@ would yield
98135
showHelp bool
99136
showLicense bool
100137
showVersion bool
138+
inputFName string
101139
outputFName string
102140

103141
// Application Specific Options
104-
update bool
105-
overwrite bool
142+
update bool
143+
overwrite bool
144+
createRoot bool
106145
)
107146

108147
func init() {
@@ -113,12 +152,15 @@ func init() {
113152
flag.BoolVar(&showLicense, "license", false, "display license")
114153
flag.BoolVar(&showVersion, "v", false, "display version")
115154
flag.BoolVar(&showVersion, "version", false, "display version")
155+
flag.StringVar(&inputFName, "i", "", "input filename (for root object)")
156+
flag.StringVar(&inputFName, "input", "", "input filename (for root object)")
116157
flag.StringVar(&outputFName, "o", "", "output filename")
117158
flag.StringVar(&outputFName, "output", "", "output filename")
118159

119160
// Application Specific Options
120-
flag.BoolVar(&update, "update", false, "copy unique key/values from second object into the first")
121-
flag.BoolVar(&overwrite, "overwrite", false, "copy all key/values from second object into the first")
161+
flag.BoolVar(&createRoot, "create", false, "create an empty root object, {}")
162+
flag.BoolVar(&update, "update", false, "copy new key/values pairs into root object")
163+
flag.BoolVar(&overwrite, "overwrite", false, "copy all key/values into root object")
122164
}
123165

124166
func main() {
@@ -129,8 +171,8 @@ func main() {
129171
// Configuration and command line interation
130172
cfg := cli.New(appName, "DATATOOLS", fmt.Sprintf(datatools.LicenseText, appName, datatools.Version), datatools.Version)
131173
cfg.UsageText = fmt.Sprintf(usage, appName)
132-
cfg.DescriptionText = fmt.Sprintf(description, appName)
133-
cfg.ExampleText = fmt.Sprintf(examples, appName, appName, appName, appName)
174+
cfg.DescriptionText = fmt.Sprintf(description, appName, appName, appName)
175+
cfg.ExampleText = fmt.Sprintf(examples, appName, appName, appName, appName, appName, appName)
134176

135177
if showHelp == true {
136178
fmt.Println(cfg.Usage())
@@ -152,21 +194,42 @@ func main() {
152194
os.Exit(1)
153195
}
154196

197+
in, err := cli.Open(inputFName, os.Stdin)
198+
if err != nil {
199+
fmt.Fprintf(os.Stderr, "%s\n", err)
200+
os.Exit(1)
201+
}
202+
defer cli.CloseFile(inputFName, in)
203+
155204
out, err := cli.Create(outputFName, os.Stdout)
156205
if err != nil {
157206
fmt.Fprintf(os.Stderr, "%s\n", err)
158207
os.Exit(1)
159208
}
160209
defer cli.CloseFile(outputFName, out)
161210

162-
if len(args) < 2 {
163-
fmt.Println(cfg.Usage())
211+
// Make sure we have some JSON objects to join...
212+
if len(args) < 1 {
213+
fmt.Fprintln(os.Stderr, cfg.Usage())
214+
fmt.Fprintln(os.Stderr, "Missing JSON document(s) to join")
164215
os.Exit(1)
165216
}
166217

167218
outObject := map[string]interface{}{}
168219
newObject := map[string]interface{}{}
169220

221+
// READ in the JSON document if present on standard in or specified with -i.
222+
if createRoot == false {
223+
buf, err := ioutil.ReadAll(in)
224+
if err != nil {
225+
fmt.Fprintf(os.Stderr, "%s\n", err)
226+
os.Exit(1)
227+
}
228+
if err := json.Unmarshal(buf, &outObject); err != nil {
229+
log.Fatal(err)
230+
}
231+
}
232+
170233
for _, arg := range args {
171234
src, err := ioutil.ReadFile(arg)
172235
if err != nil {

datatools.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import (
3535
)
3636

3737
const (
38-
Version = "v0.0.12"
38+
Version = "v0.0.13"
3939

4040
LicenseText = `
4141
%s %s

docs/jsonjoin.md

+63-16
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,51 @@
11

22
# USAGE
33

4-
## jsonjoin [OPTIONS] JSON_FILE_1 JSON_FILE_2
4+
## jsonjoin [OPTIONS] JSON_FILE_1 [JSON_FILE_2 ...]
55

66
## SYSNOPSIS
77

8-
jsonjoin is a command line tool that takes two (or more) JSON object
9-
documents and combines into a new JSON object document based on
10-
the options chosen.
8+
jsonjoin is a command line tool that takes one (or more) JSON objects files
9+
and joins them to a root JSON object read from standard input (or
10+
file identified by -input option). By default the resulting
11+
joined JSON object is written to standard out.
12+
13+
The default behavior for jsonjoin is to create key/value pairs
14+
based on the joined JSON document names and their contents.
15+
This can be thought of as a branching behavior. Each additional
16+
file becomes a branch and its key/value pairs become leafs.
17+
The root JSON object is assumed to come from standard input
18+
but can be designated by the -input option or created by the
19+
-create option. Each additional file specified as a command line
20+
argument is then treated as a new branch.
21+
22+
In addition to the branching behavior you can join JSON objects in a
23+
flat manner. The flat joining process can be ether non-distructive
24+
adding new key/value pairs (-update option) or distructive
25+
overwriting key/value pairs (-overwrite option).
26+
27+
Note: jsonjoin doesn't support a JSON array as the root JSON object.
1128

1229
## OPTIONS
1330

31+
-create create an empty root object, {}
1432
-h display help
1533
-help display help
34+
-i input filename (for root object)
35+
-input input filename (for root object)
1636
-l display license
1737
-license display license
1838
-o output filename
1939
-output output filename
20-
-overwrite copy all key/values from second object into the first
21-
-update copy unique key/values from second object into the first
40+
-overwrite copy all key/values into root object
41+
-update copy new key/values pairs into root object
2242
-v display version
2343
-version display version
2444

2545
## EXAMPLES
2646

27-
### Joining two JSON objects (maps)
47+
Consider two JSON objects one in person.json and another
48+
in profile.json.
2849

2950
person.json containes
3051

@@ -39,24 +60,49 @@ profile.json containes
3960
"email": "[email protected]" }
4061
```
4162

42-
A simple join of person.json with profile.json
63+
A simple join of person.json with profile.json (note the
64+
-create option)
65+
66+
```shell
67+
jsonjoin -create person.json profile.json
68+
```
69+
70+
would yeild and object like
71+
72+
```json
73+
{
74+
"person": { "name": "Doe, Jane", "email":"[email protected]",
75+
"age": 42},
76+
"profile": { "name": "Doe, Jane", "bio": "World renowned geophysist.",
77+
"email": "[email protected]" }
78+
}
79+
```
80+
81+
Likewise if you want to treat person.json as the root object and add
82+
profile.json as a branch try
4383

4484
```shell
45-
jsonjoin person.json profile.json
85+
cat person.json | jsonjoin profile.json
4686
```
4787

48-
would yeild
88+
or
89+
90+
```shell
91+
jsonjoin -i person.json profile.json
92+
```
93+
94+
this yields an object like
4995

5096
```json
5197
{
52-
"person": { "name": "Doe, Jane", "email":"[email protected]", "age": 42},
98+
"name": "Doe, Jane", "email":"[email protected]", "age": 42,
5399
"profile": { "name": "Doe, Jane", "bio": "World renowned geophysist.",
54100
"email": "[email protected]" }
55101
}
56102
```
57103

58104
You can modify this behavor with -update or -overwrite. Both options are
59-
order dependant (e.g. not associative, A update B does
105+
order dependant (i.e. not associative, A update B does
60106
not necessarily equal B update A).
61107

62108
+ -update will add unique key/values from the second object to the first object
@@ -65,7 +111,7 @@ not necessarily equal B update A).
65111
Running
66112

67113
```shell
68-
jsonjoin -update person.json profile.json
114+
jsonjoin -create -update person.json profile.json
69115
```
70116

71117
would yield
@@ -78,7 +124,7 @@ would yield
78124
Running
79125

80126
```shell
81-
jsonjoin -update profile.json person.json
127+
jsonjoin -create -update profile.json person.json
82128
```
83129

84130
would yield
@@ -92,7 +138,7 @@ would yield
92138
Running
93139

94140
```shell
95-
jsonjoin -overwrite person.json profile.json
141+
jsonjoin -create -overwrite person.json profile.json
96142
```
97143

98144
would yield
@@ -102,4 +148,5 @@ would yield
102148
"bio": "World renowned geophysist." }
103149
```
104150

105-
jsonjoin v0.0.12
151+
152+
jsonjoin v0.0.13

0 commit comments

Comments
 (0)