At the end of the JSON and Go blog post you'll find this sample program:
package main
import (
"encoding/json"
"log"
"os"
)
func main() {
dec := json.NewDecoder(os.Stdin)
enc := json.NewEncoder(os.Stdout)
for {
var v map[string]interface{}
if err := dec.Decode(&v); err != nil {
log.Println(err)
return
}
for k := range v {
if k != "Name" {
delete(v, k)
}
}
if err := enc.Encode(&v); err != nil {
log.Println(err)
}
}
}
I compiled this with go build json_decoder.go
and then ran the program like so in bash:
echo '{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}' | json_decoder
and received this output:
{"Name":"Wednesday"}
2019/08/17 22:09:20 EOF
The first line of output is exactly what I'd expect. But where is the line 2019/08/17 22:09:20 EOF
coming from?
When EOF
is reached the decoder returns io.EOF
which is then is being output by the logger log.Println(err)
with a timestamp prepended.
You can check for EOF
when decoding like this for example
if err := dec.Decode(&v); err != nil {
if err != io.EOF {
log.Println(err)
}
return
}
Output:
➜ echo '{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}' | ./json_decoder {"Name":"Wednesday"}
log.Println(err)
That logger writes to standard error and prints the date and time of each logged message.
You are seeing both stdout
and stderr
so:
The solution is to redirect the stdout
to a file (or to another pipe):
echo '{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}' | ./jsonio > file.json
Output (which is stderr
):
2019/08/17 20:35:40 EOF
Then see the file content (which is stdout
):
cat file.json
{"Name":"Wednesday"}
You may discard stderr
(not recommended, but for test purpose) or redirect stderr
:
echo '{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}' | ./jsonio 2>/dev/null
Output (which is stdout
):
{"Name":"Wednesday"}
Or don't show the EOF
at all (note: you'll see other errors like incorrect JSON errors in stderr
):
package main
import (
"encoding/json"
"io"
"log"
"os"
)
func main() {
dec := json.NewDecoder(os.Stdin)
enc := json.NewEncoder(os.Stdout)
for {
var v map[string]interface{}
if err := dec.Decode(&v); err != nil {
if err != io.EOF {
log.Println(err)
}
return
}
for k := range v {
if k != "Name" {
delete(v, k)
}
}
if err := enc.Encode(&v); err != nil {
log.Println(err)
}
}
}