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

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.


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


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/