2013-01-06 19 views
7

Mam strukturę z członkiem []uint8 i piszę to z json.Marshal. Kłopot polega na tym, że interpretuje on wartości uint8 s i wypisuje łańcuch, a nie tablicę liczb.Jak zabezpieczyć tablicę bajtów/uint8 jako tablicę json w Go?

Mogę to uruchomić, jeśli jest to []int, ale nie chcę przydzielać i kopiować elementów, jeśli mogę tego uniknąć. Czy mogę?

+0

Jak powiedziałem w odpowiedzi na pytanie, używam 'json.Marshal'. Moje pytanie nie dotyczy "fmt", dotyczy biblioteki 'json'. – Joe

+0

(Miałem komentarz z pytaniem o to, jak je wypisałem, autor skasował go po tym, jak odpowiedziałem, a także mogę zachować moją odpowiedź.) – Joe

Odpowiedz

13

Zgodnie z docs, []byte zostanie zakodowany jako ciąg Base64.

„wartości tablicowe i plaster kodują postaci tablic JSON tym wyjątkiem, że [] Bajt koduje jako zakodowany ciąg base64 i zerowe plaster koduje jako zerowy obiektu JSON”.

Więc myślę, że być może trzeba będzie dokonać struct implementować interfejs Marshaler wdrażając własny MarshalJSON metodę, która sprawia, że ​​bardziej pożądane kodowanie JSON tablicy z twojej []uint8.

Weźmy ten przykład:

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


A może lepszym pomysłem byłoby stworzenie nowego typu, który ma []uint8 jako podstawowego rodzaju, marki tego typu A Marshaler, i używaj tego typu w twojej strukturze.

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

Brilliant. Myślę, że druga opcja jest nieco bardziej przyszłościowa. Dziękuję bardzo. – Joe

+0

@Joe: Nie ma za co. I zaktualizowałem go, aby był bardziej kompletny, obsługując 'nil' slice jako' null'. –

Powiązane problemy