go encoding/json 패키지 데이터 처리 설명

48699 단어 #gopackages
1. 소개
JSON은 경량급 데이터 교환 형식으로 전후단 데이터 교환으로 자주 사용되며 Go는 encoding/json 패키지에서 JSON에 대한 지원을 제공한다.
2. 사용법
2.1 struct 서열화
Go struct를 JSON 객체로 시리얼화하고 Go는 Marshal 방법을 제공하며 의미와 같이 시리얼화하고 함수 서명은 다음과 같습니다.
func Marshal(v interface{}) ([]byte, error)

제1종 서법
package main
import (
    "encoding/json"
    "fmt"
)
type Message struct {
    Name string
    Body string
    Time int64
}

func main() {
   m := Message{"Liming", "Hello", 1294706395881547}
   b, err := json.Marshal(m) 
   if err != nil {
     fmt.Println(err)
   }
   fmt.Println(string(b))
}
$ go run json1.go
{"Name":"Liming","Body":"Hello","Time":1294706395881547}

두 번째 쓰기
package main
import (
    "encoding/json"
    "fmt"
)

type Product struct {
    Name      string
    ProductID int64
    Number    int
    Price     float64
    IsOnSale  bool
}

func main() {
    p := &Product{}
    p.Name = "apple 8P"
    p.IsOnSale = true
    p.Number = 1000
    p.Price = 4499.00
    p.ProductID = 1
    data, _ := json.Marshal(p)
    fmt.Println(string(data))
}
$ go run json2.go
{"Name":"apple 8P","ProductID":1,"Number":1000,"Price":4499,"IsOnSale":true}

Go에서 모든 유형이 서열화되는 것은 아닙니다.
  • JSON object 키는 string
  • 만 지원
  • Channel,complex,function 등 type을 서열화할 수 없음
  • 데이터에 순환 인용이 존재하면 서열화할 수 없습니다. 서열화할 때 귀속되기 때문입니다
  • Pointer 서열화 이후 지향하는 값 또는 nil
  • 주의해야 할 것은 struct에서 내보내기를 지원하는 필드만 JSON 패키지 서열화, 즉 알파벳 대문자field입니다.
    2.2 Struct Tag
    Struct tag은 Marshal 및 Unmarshal 함수의 데이터 정렬 및 반정렬 방법을 결정합니다.
    package main
    import (
        "encoding/json"
        "fmt"
    )
    
    type Product struct {
        Name      string  `json:"name"`
        ProductID int64   `json:"-"` //         
        Number    int     `json:"number"`
        Price     float64 `json:"price"`
        IsOnSale  bool    `json:"is_on_sale,string"`
    }
    func main() {
        p := &Product{}
        p.Name = "apple 8P"
        p.IsOnSale = true
        p.Number = 1000
        p.Price = 4499.00
        p.ProductID = 1
        data, _ := json.Marshal(p)
        fmt.Println(string(data))
    }
    
    $ go run json4.go
    {"name":"apple 8P","number":1000,"price":4499,"is_on_sale":"true"}
    
    omitempty,tag에omitempy를 추가하면 서열화할 때 0값이나 빈값이나false를 무시할 수 있습니다.
    package main
    import (
        "encoding/json"
        "fmt"
    )
    
    type Product struct {
        Name      string  `json:"name"`
        ProductID int64   `json:"product_id,omitempty"` 
        Number    int     `json:"number"`
        Price     float64 `json:"price"`
        IsOnSale  bool    `json:"is_on_sale,omitempty"`
    }
    
    func main() {
        p := &Product{}
        p.Name = "apple 8P"
        p.IsOnSale = false
        p.Number = 1000
        p.Price = 4499.00
        p.ProductID = 0
        data, _ := json.Marshal(p)
        fmt.Println(string(data))
    }
    
    $ go  run json5.go
    {"name":"apple 8P","number":1000,"price":4499}
    

    2.3 struct 역서열화
    역정렬 함수는 Unmarshal이며 함수 서명은 다음과 같습니다.
    func Unmarshal(data []byte, v interface{}) error
    
    package main
    import (
    	"encoding/json"
    	"fmt"
    )
     
    type Change struct {
    	Mid     int      //  Id
    	Actions []string //      "add"  "view"  "delete"  "update"
    }
    type Change_slice struct {
    	ChgArr []Change //             
    }
    func main() {
            var str string = `{"ChgArr":[{"Mid":1,"Actions":["view","add"]},{"Mid":2,"Actions":["delete","add","update"]}]}`
    	var msgs Change_slice
    	err := json.Unmarshal([]byte(str), &msgs)
    	if err != nil {
    		fmt.Println("Can't decode json message", err)
    	} else {
    		fmt.Println(msgs.ChgArr[1].Mid)
    	}
    
    }
    
    $  go run json3.go
    2
    

    2.4 태그 역정렬
    태그(tag)가 있는 구조체(struct)
    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    // Product _
    type Product struct {
        Name      string  `json:"name"`
        ProductID int64   `json:"product_id,string"`
        Number    int     `json:"number,string"`
        Price     float64 `json:"price,string"`
        IsOnSale  bool    `json:"is_on_sale,string"`
    }
    
    func main() {
    
        var data = `{"name":"apple 8P","product_id":"10","number":"10000","price":"6000","is_on_sale":"true"}`
        p := &Product{}
        err := json.Unmarshal([]byte(data), p)
        if err != nil {
           fmt.Println(err)
        }
        fmt.Println(*p)
    }
    
    $ go run json6.go
    {apple 8P 10 10000 6000 true}
    

    또 다른 반서열화 (형식)
    var m Product
    err := json.Unmarshal(b, &m)
    

    2.5 interface {} 역서열화
    알 수 없는 형식 json
    package main
    
    import (
    	"encoding/json"
    	"fmt"
    )
    
    func main() {
    	a := `{"name":"chalvern.github.io","full_name":"chalvern/chalvern.github.io","private":false,"owner":{"login":"chalvern","html_url":"https://github.com/chalvern"},"html_url":"https://github.com/chalvern/chalvern.github.io","description":"jingwei.link blog"}`
    
    	var jingweiI interface{}
    	err := json.Unmarshal([]byte(a), &jingweiI)
            if err != nil {
               fmt.Println(err)
            }
    	fmt.Printf("%#v 
    %#v
    "
    , jingweiI) // key jingweiM, ok := jingweiI.(map[string]interface{}) if !ok { fmt.Println("DO SOMETHING!") return } fmt.Printf("%#v
    "
    , jingweiM["name"]) // owner, ok := jingweiM["owner"].(map[string]interface{}) if !ok { fmt.Println("DO SOMETHING!") return } fmt.Printf("%#v
    "
    , owner["login"]) }
    $ go run json8.go
    map[string]interface {}{"description":"jingwei.link blog", "full_name":"chalvern/chalvern.github.io", "html_url":"https://github.com/chalvern/chalvern.github.io", "name":"chalvern.github.io", "owner":map[string]interface {}{"html_url":"https://github.com/chalvern", "login":"chalvern"}, "private":false} 
     %!v(MISSING) 
    "chalvern.github.io"
    "chalvern"
    

    2.6 인코딩
    부호화
    json.NewEncoder(<Writer>).encode(v)
    json.Marshal(&v)
    

    디코딩
    json.NewDecoder(<Reader>).decode(&v)
    json.Unmarshal([]byte, &v)
    

    Go는 마스홀과 unmarshal 함수를 제외하고 Decoder와 Encoder가 stream JSON을 처리하고 흔한 Request의 Body, 파일 등을 제공한다.
    $ cat post.json 
    {
      "name":"apple 8P",
      "product_id":10,
      "number":10000,
      "price":6000,
      "is_on_sale":"true"
    }
    
    $ cat json9.go 
    package main
    import (
     "encoding/json"
     "fmt"
     "io"
     "os"
    )
    
    type Product struct {
        Name      string
        ProductID int64
        Number    int
        Price     float64
        IsOnSale  bool
    }
    
    
    func main() {
      jsonFile, err := os.Open("post.json")
      if err != nil {
          fmt.Println("Error opening json file:", err)
          return
      }
    
      defer jsonFile.Close()
      decoder := json.NewDecoder(jsonFile)
      for {
          var post Product
          err := decoder.Decode(&post)
          if err == io.EOF {
    	  break
          }
    
          if err != nil {
    	  fmt.Println("error decoding json:", err)
    	  return
          }
    
          fmt.Println(post)
      }
    }
    
    $ go  run json9.go
    {apple 8P 0 10000 6000 false}
    

    3. 실전
    3.1 인코딩 비교
    package main
    
    import (
        "encoding/json"
        "fmt"
        "bytes"
        "strings"
    )
    
    type Person struct {
        Name string `json:"name"`
        Age int `json:"age"`
    }
    
    func main()  {
        // 1.    json.Marshal   
        person1 := Person{"  ", 24}
        bytes1, err := json.Marshal(&person1)
        if err == nil {
            //          []byte
            fmt.Println("json.Marshal     : ", string(bytes1))
        }
    
        // 2.    json.Unmarshal   
        str := `{"name":"  ","age":25}`
        // json.Unmarshal         ,          []byte   
        bytes2 := []byte(str) //           
        var person2 Person    //           
        if json.Unmarshal(bytes2, &person2) == nil {
            fmt.Println("json.Unmarshal     : ", person2.Name, person2.Age)
        }
    
        // 3.    json.NewEncoder   
        person3 := Person{"  ", 30}
        //         buffer
        bytes3 := new(bytes.Buffer)
        _ = json.NewEncoder(bytes3).Encode(person3)
        if err == nil {
            fmt.Print("json.NewEncoder     : ", string(bytes3.Bytes()))
        }
    
        // 4.    json.NewDecoder   
        str4 := `{"name":"  ","age":28}`
        var person4 Person
        //      string reader     
        err = json.NewDecoder(strings.NewReader(str4)).Decode(&person4)
        if err == nil {
            fmt.Println("json.NewDecoder     : ", person4.Name, person4.Age)
        }
    }
    

    결과:
    json.Marshal     :  {"name":"  ","age":24}
    json.Unmarshal     :     25
    json.NewEncoder     : {"name":"  ","age":30}
    json.NewDecoder     :     28
    

    3.2 알 수 없는 형식의 json
    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    func main() {
        b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
    
        var f interface{}
        json.Unmarshal(b, &f)
    
        m := f.(map[string]interface{})
        fmt.Println(m["Parents"])  //    json   
        fmt.Println(m["a"] == nil) //        
    }
    
    $ go run json11.go
    [Gomez Morticia]
    true
    

    참조 연결:https://learnku.com/go/t/23565/golang-json-coding-and-decoding-summary https://jingwei.link/2019/03/15/golang-json-unmarshal-using.html https://sanyuesha.com/2018/05/07/go-json/

    좋은 웹페이지 즐겨찾기