douxuanpa8298
2018-06-26 05:30
浏览 100
已采纳

在Golang中从stdin读取json对象

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?

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • duanchu7271 2018-06-26 06:15
    已采纳

    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)
            }
        }
    }
    
    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • donglinxi1467 2018-06-26 05:37

    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.

    • Read from stdin into a buffer that is large enough to hold the entire JSON object.
    • Unmarshal the JSON object

    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)
    }
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题