2013-01-06 17 views
7

Ho una struttura con un membro []uint8 e la sto scrivendo con json.Marshal. Il problema è che sta interpretando lo uint8 s come char s e restituisce una stringa anziché una serie di numeri.Come eseguire il marshalling di un array byte/uint8 come array json in Go?

Posso farlo funzionare se è un []int, ma non voglio dover allocare e copiare gli articoli se posso evitarlo. Posso?

+0

Come ho detto nella domanda, sto usando 'json.Marshal'. La mia domanda non riguarda 'fmt', riguarda la libreria' json'. – Joe

+0

(Ho fatto un commento chiedendo come stavo emettendo l'immagine, l'autore l'ha cancellato dopo che ho risposto. Potrebbe anche mantenere la mia risposta.) – Joe

risposta

13

In base allo docs, un []byte sarà codificato come una stringa Base64.

"valori di matrice e fetta codificano come array JSON, tranne che [] byte codifica come stringa codifica base64, e una fetta nil codifica come oggetto JSON nullo."

Quindi penso che potrebbe essere necessario per rendere la vostra struct implementi l'interfaccia Marshaler implementando il proprio MarshalJSON metodo che rende una codifica gamma JSON più desiderabile dal vostro []uint8.

Prendete questo esempio:

import "fmt" 
import "encoding/json" 
import "strings" 

type Test struct { 
    Name string 
    Array []uint8 
} 

func (t *Test) MarshalJSON() ([]byte, error) { 
    var array string 
    if t.Array == nil { 
     array = "null" 
    } else { 
     array = strings.Join(strings.Fields(fmt.Sprintf("%d", t.Array)), ",") 
    } 
    jsonResult := fmt.Sprintf(`{"Name":%q,"Array":%s}`, t.Name, array) 
    return []byte(jsonResult), nil 
} 

func main() { 
    t := &Test{"Go", []uint8{'h', 'e', 'l', 'l', 'o'}} 

    m, err := json.Marshal(t) 
    if err != nil { 
     fmt.Println(err) 
    } 
    fmt.Printf("%s", m) // {"Name":"Go","Array":[104,101,108,108,111]} 
} 

http://play.golang.org/p/Tip59Z9gqs


O forse un idea migliore sarebbe quella di fare un nuovo tipo che ha []uint8 come tipo di fondo, fanno quel tipo di Marshaler, e usa quel tipo nella tua struct.

import "fmt" 
import "encoding/json" 
import "strings" 

type JSONableSlice []uint8 

func (u JSONableSlice) MarshalJSON() ([]byte, error) { 
    var result string 
    if u == nil { 
     result = "null" 
    } else { 
     result = strings.Join(strings.Fields(fmt.Sprintf("%d", u)), ",") 
    } 
    return []byte(result), nil 
} 

type Test struct { 
    Name string 
    Array JSONableSlice 
} 

func main() { 
    t := &Test{"Go", []uint8{'h', 'e', 'l', 'l', 'o'}} 

    m, err := json.Marshal(t) 
    if err != nil { 
     fmt.Println(err) 
    } 
    fmt.Printf("%s", m) // {"Name":"Go","Array":[104,101,108,108,111]} 
} 

http://play.golang.org/p/6aURXw8P5d

+0

Brillante. Penso che la seconda opzione sia un po 'più a prova di futuro. Grazie mille. – Joe

+0

@Joe: prego. E ho aggiornato per renderlo un po 'più completo gestendo una slice 'nil' come' null'. –

Problemi correlati