How do you marshal a sql.NullString such that the output is flattened to give just the value in go?

后端 未结 3 2040
没有蜡笔的小新
没有蜡笔的小新 2021-02-15 05:18

Given a go struct

type Company struct {
    ID   int             `json:\"id\"`              
    Abn  sql.NullString  `json:\"abn,string\"`
}

w

相关标签:
3条回答
  • 2021-02-15 05:50

    The question suggests that you want to expose your database structure as JSON (presumably REST-ish) API. Unless the project is going to have a short lifespan or the logic layer is trivial, such an approach is considered an antipattern. The internals (database structure) become coupled with the external interface (API) and may result in a high cost of making a change.

    I'm attaching some reads as Google is full of tutorials on how to do the opposite:

    https://lostechies.com/jimmybogard/2016/05/12/entities-arent-resources-resources-arent-representations/

    https://thorben-janssen.com/dont-expose-entities-in-api/

    0 讨论(0)
  • 2021-02-15 05:56

    Here is the code,

    package main
    
    import (
        "database/sql"
        "encoding/json"
        "fmt"
        "log"
    )
    
    //Company details
    type Company struct {
        ID  int        `json:"id"`
        Abn NullString `json:"abn"`
    }
    
    //NullString is a wrapper around sql.NullString
    type NullString sql.NullString
    
    //MarshalJSON method is called by json.Marshal,
    //whenever it is of type NullString
    func (x *NullString) MarshalJSON() ([]byte, error) {
        if !x.Valid {
            return []byte("null"), nil
        }
        return json.Marshal(x.String)
    }
    
    func main() {
        company := &Company{}
        company.ID = 68
        //create new NullString value
        nStr := sql.NullString{String: "hello", Valid: true}
        //cast it
        company.Abn = NullString(nStr)
        result, err := json.Marshal(company)
        if err != nil {
            log.Println(err)
        }
        fmt.Println(string(result))
    }
    

    Here is the blog post which explains it in detail.

    0 讨论(0)
  • 2021-02-15 05:59

    You cannot, at least not using just sql.NullString and encoding/json.

    What you can do is to declare a custom type that embeds sql.NullString and have that custom type implement the json.Marshaler interface.

    type MyNullString struct {
        sql.NullString
    }
    
    func (s MyNullString) MarshalJSON() ([]byte, error) {
        if s.Valid {
            return json.Marshal(s.String)
        }
        return []byte(`null`), nil
    }
    
    type Company struct {
        ID   int          `json:"id"`              
        Abn  MyNullString `json:"abn,string"`
    }
    

    https://play.golang.org/p/Ak_D6QgIzLb

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