How to read a json object from stdin? I want to copy and paste a json object into the stdin, read it and unmarshal it. Here is the code:
var input string
_, err := fmt.Scan(&input)
if err != nil {
fmt.Println(err)
continue
}
var record MedicalRecord
if err := json.Unmarshal([]byte(input), &record); err != nil {
log.Println(err)
continue
}
And the errors are printed to console.
> 2018/06/26 00:26:32 invalid character ':' after top-level value
> 2018/06/26 00:26:32 unexpected end of JSON input
> 2018/06/26 00:26:32 invalid character ':' after top-level value
> 2018/06/26 00:26:32 invalid character ',' after top-level value
> 2018/06/26 00:26:32 invalid character ':' after top-level value
> 2018/06/26 00:26:32 invalid character ',' after top-level value
> 2018/06/26 00:26:32 invalid character ':' after top-level value
> 2018/06/26 00:26:32 invalid character ',' after top-level value
> 2018/06/26 00:26:32 invalid character ':' after top-level value
> 2018/06/26 00:26:32 invalid character ',' after top-level value
If I'm not mistaken, Go is reading until it finds ' ' . How can I solve this problem?
Use a *json.Decoder to consume JSON from an io.Reader:
package main
import (
"encoding/json"
"log"
"os"
)
type MedicalRecord struct{}
func main() {
var record MedicalRecord
err := json.NewDecoder(os.Stdin).Decode(&record)
if err != nil {
log.Fatal(err)
}
}
You can consume multiple consecutive JSON documents by calling Decode repeatedly:
package main
import (
"encoding/json"
"io"
"log"
"os"
)
type MedicalRecord struct{}
func main() {
var record MedicalRecord
dec := json.NewDecoder(os.Stdin)
for {
err := dec.Decode(&record)
if err == io.EOF {
return
}
if err != nil {
log.Fatal(err)
}
}
}
When you call json.Unmarshal
you should have the full JSON object in hand, otherwise you're just trying to unmarshal some partial object that makes no sense to the parser.
For example:
package main
import (
"bytes"
"io"
"fmt"
"os"
"bufio"
"encoding/json"
)
func main() {
var buf bytes.Buffer
reader := bufio.NewReader(os.Stdin)
for {
line, err := reader.ReadString('
')
if err != nil {
if err == io.EOF {
buf.WriteString(line)
break // end of the input
} else {
fmt.Println(err.Error())
os.Exit(1) // something bad happened
}
}
buf.WriteString(line)
}
fmt.Printf("valid json? %v
", json.Valid(buf.Bytes()))
type MedicalRecord struct {
Name string `json:"name"`
Age int `json:"age"`
}
var record MedicalRecord
err := json.Unmarshal(buf.Bytes(), &record)
if err != nil {
fmt.Println(err.Error())
os.Exit(1) // something bad happened
}
fmt.Printf("name: %s, age: %d
", record.Name, record.Age)
}