Allez des types comme Int64
et String
ne peuvent pas stocker de valeurs nulles, j'ai donc trouvé que je pouvais utiliser sql.NullInt64 et sql.NullString pour cela.
Mais lorsque je les utilise dans un Struct et que je génère du JSON à partir du Struct avec le package json , le format est différent de celui que j'utilise régulièrement Int64
et String
types.
Le JSON a un niveau supplémentaire car le sql.Null *** est également un Struct.
Existe-t-il une bonne solution de contournement pour cela, ou dois-je ne pas utiliser de valeurs NULL dans ma base de données SQL?
Des types comme sql.NullInt64
n'implémente pas de gestion spéciale pour le marshaling ou le démarshaling JSON, donc les règles par défaut s'appliquent. Étant donné que le type est une structure, il est rassemblé en tant qu'objet avec ses champs en tant qu'attributs.
Une façon de contourner ce problème consiste à créer votre propre type qui implémente le json.Marshaller
/json.Unmarshaler
interfaces. En intégrant le sql.NullInt64
type, nous obtenons gratuitement les méthodes SQL. Quelque chose comme ça:
type JsonNullInt64 struct {
sql.NullInt64
}
func (v JsonNullInt64) MarshalJSON() ([]byte, error) {
if v.Valid {
return json.Marshal(v.Int64)
} else {
return json.Marshal(nil)
}
}
func (v *JsonNullInt64) UnmarshalJSON(data []byte) error {
// Unmarshalling into a pointer will let us detect null
var x *int64
if err := json.Unmarshal(data, &x); err != nil {
return err
}
if x != nil {
v.Valid = true
v.Int64 = *x
} else {
v.Valid = false
}
return nil
}
Si vous utilisez ce type à la place de sql.NullInt64
, il doit être encodé comme prévu.
Vous pouvez tester cet exemple ici: http://play.golang.org/p/zFESxLcd-c
Si vous utilisez le package null.v , vous n'aurez pas besoin d'implémenter les méthodes marshal ou unmarshal. C'est un surensemble des structures sql.Null et c'est probablement ce que vous voulez.
package main
import "gopkg.in/guregu/null.v3"
type Person struct {
Name string `json:"id"`
Age int `json:"age"`
NickName null.String `json:"nickname"` // Optional
}
Si vous souhaitez voir un serveur Web Golang complet qui utilise sqlite, nulls et json, vous pouvez consulter this Gist .