Assigning null to JSON fields instead of empty strings

后端 未结 5 1899
迷失自我
迷失自我 2020-11-29 23:34

Since empty string is the zero/default value for Go string, I decided to define all such fields as interface{} instead. for example



        
相关标签:
5条回答
  • 2020-11-30 00:08

    Another way actually is a workaround with using the MarhshalJSON and UnmarshalJSON interface method offered by the json lib of golang. The code is as below:

    type MyType string
    type MyStruct struct {
        A MyType `json:"my_type"`
    }
    
    func (c MyType) MarshalJSON() ([]byte, error) {
        var buf bytes.Buffer
        if len(string(c)) == 0 {
            buf.WriteString(`null`)
        } else {
            buf.WriteString(`"` + string(c) + `"`)   // add double quation mark as json format required
        }
        return buf.Bytes(), nil
    }
    
    func (c *MyType)UnmarshalJSON(in []byte) error {
        str := string(in)
        if str == `null` {
            *c = ""
            return nil
        }
        res := MyType(str)
        if len(res) >= 2 {
            res = res[1:len(res)-1]     // remove the wrapped qutation
        }
        *c = res
        return nil
    }
    

    then when using json.Marshal, the MyType value will be marshaled as null.

    0 讨论(0)
  • 2020-11-30 00:15

    Can be used https://github.com/guregu/null

    type student struct {
    FirstName  null.String `json:"first_name"`
    MiddleName null.String `json:"middle_name"`
    LastName   null.String `json:"last_name"`}
    
    0 讨论(0)
  • 2020-11-30 00:27

    You could use something like sql.NullString,use 'Valid' to check if it is a nil value.

    NullString represents a string that may be null. NullString implements the Scanner interface so it can be used as a scan destination:

    type NullString struct {
        String string
        Valid  bool // Valid is true if String is not NULL
    }
    
    var s NullString
    err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&s)
    ...
    if s.Valid {
       // use s.String
    } else {
       // NULL value
    }
    

    Please DO NOT use pointers like below:

    type student struct {
      FirstName  *string `json:"first_name"`
      MiddleName *string `json:"middle_name"`
      LastName   *string `json:"last_name"`
    }
    

    Because you need check nil value and dereference like below everywhere,and maybe cause unexpected crash somewhere:

    if obj.FirstName != nil {
       fmt.Print("%s", *obj.FirstName)
    }
    

    I have compared two solution and choosed former method in my extensively production code,it work ok.

    0 讨论(0)
  • 2020-11-30 00:34

    In json package documentation :

    Pointer values encode as the value pointed to. A nil pointer encodes as the null JSON object.

    So you can store a pointer to a string which will be encoded as a string if not nil and will be encoded as "null" if nil

    type student struct {
      FirstName  *string `json:"first_name"`
      MiddleName *string `json:"middle_name"`
      LastName   *string `json:"last_name"`
    }
    
    0 讨论(0)
  • 2020-11-30 00:34

    For the case of a json object with null strings, its easiest to use the omitempty decorator on the field.

    type student struct {
      FirstName  string `json:"first_name,omitempty"`
      MiddleName string `json:"middle_name,omitempty"`
      LastName   string `json:"last_name"`
    }
    

    With the above declaration, only if first_name was assigned will that key show up in the resultant json. last_name, on the otherhand, will always show up in the result with a value of "" if not assigned.

    Now when you start including numeric fields where 0 could be a value, using omitempty doesn't do what one would expect. A 0 value always drops the field, and we need to be able to differentiate between a 0 value and an unassigned value. Here use of library such as https://github.com/guregu/null may be advisable.

    More discussion here: https://www.sohamkamani.com/blog/golang/2018-07-19-golang-omitempty/

    0 讨论(0)
提交回复
热议问题