Skip to content

Commit a487db4

Browse files
committed
Added jsonjoin cli, bumped version number
1 parent a8e56ab commit a487db4

File tree

3 files changed

+307
-0
lines changed

3 files changed

+307
-0
lines changed

cmds/jsonjoin/jsonjoin.go

+200
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
//
2+
// jsonjoin is a command line tool that takes two JSON documents and combined
3+
// them into one depending on the options
4+
//
5+
// @author R. S. Doiel, <[email protected]>
6+
//
7+
package main
8+
9+
import (
10+
"encoding/json"
11+
"flag"
12+
"fmt"
13+
"io/ioutil"
14+
"log"
15+
"os"
16+
"path"
17+
"strings"
18+
19+
// Caltech Library Packages
20+
"github.com/caltechlibrary/cli"
21+
"github.com/caltechlibrary/datatools"
22+
)
23+
24+
var (
25+
usage = `USAGE: %s [OPTIONS] JSON_FILE_1 JSON_FILE_2`
26+
27+
description = `
28+
SYSNOPSIS
29+
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.
33+
`
34+
35+
examples = `
36+
EXAMPLES
37+
38+
Joining two JSON objects (maps)
39+
40+
person.json containes
41+
42+
{"name": "Doe, Jane", "email":"[email protected]", "age": 42}
43+
44+
profile.json containes
45+
46+
{"name": "Doe, Jane", "bio": "World renowned geophysist.",
47+
"email": "[email protected]"}
48+
49+
A simple join of person.json with profile.json
50+
51+
%s person.json profile.json
52+
53+
would yeild
54+
55+
{
56+
"person": {"name": "Doe, Jane", "email":"[email protected]", "age": 42},
57+
"profile": {"name": "Doe, Jane", "bio": "World renowned geophysist.",
58+
"email": "[email protected]"}
59+
}
60+
61+
You can modify this behavor with -add or -merge. Both options are
62+
order dependant (i.e. not guaranteed to be associative, A add B does
63+
not necessarily equal B add A).
64+
65+
+ -update will add unique key/values from the second object to the first object
66+
+ -overwrite replace key/values in first object one with second objects'
67+
68+
Running
69+
70+
%s -update person.json profile.json
71+
72+
would yield
73+
74+
{ "name": "Doe, Jane", "email":"[email protected]", "age": 42,
75+
"bio": "World renowned geophysist." }
76+
77+
Running
78+
79+
%s -update profile.json person.json
80+
81+
would yield
82+
83+
{ "name": "Doe, Jane", "age": 42,
84+
"bio": "World renowned geophysist.",
85+
"email": "[email protected]" }
86+
87+
Running
88+
89+
%s -overwrite person.json profile.json
90+
91+
would yield
92+
93+
{ "name": "Doe, Jane", "email":"[email protected]", "age": 42,
94+
"bio": "World renowned geophysist." }
95+
`
96+
97+
// Basic Options
98+
showHelp bool
99+
showLicense bool
100+
showVersion bool
101+
outputFName string
102+
103+
// Application Specific Options
104+
update bool
105+
overwrite bool
106+
)
107+
108+
func init() {
109+
// Basic Options
110+
flag.BoolVar(&showHelp, "h", false, "display help")
111+
flag.BoolVar(&showHelp, "help", false, "display help")
112+
flag.BoolVar(&showLicense, "l", false, "display license")
113+
flag.BoolVar(&showLicense, "license", false, "display license")
114+
flag.BoolVar(&showVersion, "v", false, "display version")
115+
flag.BoolVar(&showVersion, "version", false, "display version")
116+
flag.StringVar(&outputFName, "o", "", "output filename")
117+
flag.StringVar(&outputFName, "output", "", "output filename")
118+
119+
// 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")
122+
}
123+
124+
func main() {
125+
appName := path.Base(os.Args[0])
126+
flag.Parse()
127+
args := flag.Args()
128+
129+
// Configuration and command line interation
130+
cfg := cli.New(appName, "DATATOOLS", fmt.Sprintf(datatools.LicenseText, appName, datatools.Version), datatools.Version)
131+
cfg.UsageText = fmt.Sprintf(usage, appName)
132+
cfg.DescriptionText = fmt.Sprintf(description, appName)
133+
cfg.ExampleText = fmt.Sprintf(examples, appName, appName, appName, appName)
134+
135+
if showHelp == true {
136+
fmt.Println(cfg.Usage())
137+
os.Exit(0)
138+
}
139+
140+
if showLicense == true {
141+
fmt.Println(cfg.License())
142+
os.Exit(0)
143+
}
144+
145+
if showVersion == true {
146+
fmt.Println(cfg.Version())
147+
os.Exit(0)
148+
}
149+
150+
if len(args) == 0 {
151+
fmt.Fprintf(os.Stderr, "Need to provide at least one template name\n")
152+
os.Exit(1)
153+
}
154+
155+
out, err := cli.Create(outputFName, os.Stdout)
156+
if err != nil {
157+
fmt.Fprintf(os.Stderr, "%s\n", err)
158+
os.Exit(1)
159+
}
160+
defer cli.CloseFile(outputFName, out)
161+
162+
if len(args) < 2 {
163+
fmt.Println(cfg.Usage())
164+
os.Exit(1)
165+
}
166+
167+
outObject := map[string]interface{}{}
168+
newObject := map[string]interface{}{}
169+
170+
for _, arg := range args {
171+
src, err := ioutil.ReadFile(arg)
172+
if err != nil {
173+
log.Fatal(err)
174+
}
175+
if err := json.Unmarshal(src, &newObject); err != nil {
176+
log.Fatal(err)
177+
}
178+
switch {
179+
case update == true:
180+
for k, v := range newObject {
181+
if _, ok := outObject[k]; ok != true {
182+
outObject[k] = v
183+
}
184+
}
185+
case overwrite == true:
186+
for k, v := range newObject {
187+
outObject[k] = v
188+
}
189+
default:
190+
key := strings.TrimSuffix(path.Base(arg), ".json")
191+
outObject[key] = newObject
192+
}
193+
}
194+
195+
src, err := json.Marshal(outObject)
196+
if err != nil {
197+
log.Fatal(err)
198+
}
199+
fmt.Fprintf(out, "%s", src)
200+
}

demos/profile.json

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{"name": "Doe, Jane", "bio": "World renowned geophysist.", "email": "[email protected]"}
2+

docs/jsonjoin.md

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# USAGE
2+
3+
## jsonjoin [OPTIONS] JSON_FILE_1 JSON_FILE_2
4+
5+
## SYSNOPSIS
6+
7+
jsonjoin is a command line tool that takes two (or more) JSON object
8+
documents and combines into a new JSON object document based on
9+
the options chosen.
10+
11+
## OPTIONS
12+
13+
-h display help
14+
-help display help
15+
-l display license
16+
-license display license
17+
-o output filename
18+
-output output filename
19+
-overwrite copy all key/values from second object into the first
20+
-update copy unique key/values from second object into the first
21+
-v display version
22+
-version display version
23+
24+
## EXAMPLES
25+
26+
### Joining two JSON objects (maps)
27+
28+
person.json containes
29+
30+
```json
31+
{"name": "Doe, Jane", "email":"[email protected]", "age": 42}
32+
```
33+
34+
profile.json containes
35+
36+
```json
37+
{"name": "Doe, Jane", "bio": "World renowned geophysist.",
38+
"email": "[email protected]"}
39+
```
40+
41+
A simple join of person.json with profile.json
42+
43+
```shell
44+
jsonjoin person.json profile.json
45+
```
46+
47+
would yeild
48+
49+
```json
50+
{
51+
"person": {"name": "Doe, Jane", "email":"[email protected]", "age": 42},
52+
"profile": {"name": "Doe, Jane", "bio": "World renowned geophysist.",
53+
"email": "[email protected]"}
54+
}
55+
```
56+
57+
You can modify this behavor with -add or -merge. Both options are
58+
order dependant (i.e. not guaranteed to be associative, A add B does
59+
not necessarily equal B add A).
60+
61+
+ -update will add unique key/values from the second object to the first object
62+
+ -overwrite replace key/values in first object one with second objects'
63+
64+
Running
65+
66+
```shell
67+
jsonjoin -update person.json profile.json
68+
```
69+
70+
would yield
71+
72+
```json
73+
{ "name": "Doe, Jane", "email":"[email protected]", "age": 42,
74+
"bio": "World renowned geophysist." }
75+
```
76+
77+
Running
78+
79+
```shell
80+
jsonjoin -update profile.json person.json
81+
```
82+
83+
would yield
84+
85+
```json
86+
{ "name": "Doe, Jane", "age": 42,
87+
"bio": "World renowned geophysist.",
88+
"email": "[email protected]" }
89+
```
90+
91+
Running
92+
93+
```shell
94+
jsonjoin -overwrite person.json profile.json
95+
```
96+
97+
would yield
98+
99+
```json
100+
{ "name": "Doe, Jane", "email":"[email protected]", "age": 42,
101+
"bio": "World renowned geophysist." }
102+
```
103+
104+
105+
jsonjoin v0.0.12

0 commit comments

Comments
 (0)