2015-10-12 7 views
13

Vai valori come int64, stringa non può memorizzare valori nulli. Quindi ho scoperto che noi potremmo usare sql.NullInt64 e sql.NullString.Come posso lavorare con i valori sql NULL e JSON in Golang in modo corretto?

Ma quando li uso in una struct e generi JSON dalla struct con il pacchetto JSON, il formato non è più come un tempo quando usavo int64 e string regolari. Quello che voglio dire è che ha un livello aggiuntivo perché il sql.Null *** è anche una struttura.

C'è una buona soluzione per questo, o non dovrei usare NULL nel mio database MySQL?

+0

Si dovrebbe spiegare che cosa si intende per "non come ha usato per essere quando ho usato Int64 regolare e la stringa" nella sua interrogazione. – kostya

+1

hai provato a usare i puntatori a ints, sì? cioè: var anint * int, quindi usando & anint se è nullo, il puntatore sarà nullo. funziona bene con la codifica JSON. questo funziona con gorp di sicuro, non sono stati testati con pacchetto SQL diretto sebbene –

risposta

28

Tipi come sql.NullInt64 non implementano alcuna gestione speciale per il marshalling o unmarshaling JSON, pertanto si applicano le regole predefinite. Poiché il tipo è una struttura, viene eseguito il marshalling come oggetto con i relativi campi come attributi.

Un modo per aggirare questo è creare il proprio tipo che implementa le interfacce json.Marshaller/json.Unmarshaler. Incorporando il tipo sql.NullInt64, otteniamo i metodi SQL gratuitamente. Qualcosa di simile a questo:

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 
} 

Se si utilizza questo tipo al posto di sql.NullInt64, dovrebbe essere codificato come previsto.

È possibile verificare questo esempio qui: http://play.golang.org/p/zFESxLcd-c

+2

Che ottima soluzione! Grazie! – Alex

+6

Il pacchetto 'null' è altrettanto utile. https://github.com/guregu/null Mi piace. –

+0

Forse è superfluo dire, ma è fantastico avere dei giochi di ruolo in Golang per dimostrare cose del genere - fa davvero una grande differenza per l'adozione della lingua. Grazie per l'ottima risposta. – NSTJ

Problemi correlati