douciwang6819 2017-11-16 21:39
浏览 6
已采纳

为非内置类型定义自定义解组

Most of us know that a JSON object can be unmarshaled with JSON tags:

var jsonData = `{"name": "Brown Bear"}`

type Elephant struct {
    Name string `json:"name"`
}

This is because string is a built in types. But what if Name were not a built in type, and we wanted to use this type across different structs?

var jsonData = `{"name": "Brown Bear"}`

type Elephant struct {
    Name Name   `json:"name"`  // Unmarshalling fails here
}

type Feline struct {
    Name Name   `json:"name"`  // Unmarshalling fails here
}

type Bear struct {
    Name Name   `json:"name"`  // Unmarshalling fails here
}

type Name struct {
    CommonName     string
    ScientificName string  // This field should intentionally be blank
}

Is there a way we can define the Name type so that the json unmarshaller knows how to unmarshal it?

PS: The solution I want to avoid is creating UnmarshalJSON methods for Elephant, Feline, and Bear above. It would be better to create a method just for the Name type.

  • 写回答

1条回答 默认 最新

  • dongmiao520892 2017-11-16 21:57
    关注

    See the json.Marshaler and json.Unmarshaler types in the encoding/json package which allow you to define custom JSON en/decoding functions for arbitrary types.

    package main
    
    import (
      "encoding/json"
      "fmt"
    )
    
    type Name struct {
      CommonName     string
      ScientificName string
    }
    
    func (n *Name) UnmarshalJSON(bytes []byte) error {
      var name string
      err := json.Unmarshal(bytes, &name)
      if err != nil {
        return err
      }
      n.CommonName = name
      n.ScientificName = ""
      return nil
    }
    
    type Elephant struct {
      Name Name `json:"name"`
      Age  int  `json:"age"`
    }
    
    func main() {
      alice := Elephant{}
      aliceJson := `{"name":"Alice","age":2}`
      err := json.Unmarshal([]byte(aliceJson), &alice)
      if err != nil {
        panic(err)
      }
      fmt.Printf("%#v
    ", alice)
    }
    // main.Elephant{Name:main.Name{CommonName:"Alice", ScientificName:""}, Age:2}
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?