2015-04-21 10 views
5

Chcę dostosować format kodowania struktury, ale dostałem błąd: json: błąd wywołania MarshalJSON dla typu main.Info: nieprawidłowy znak 'o' w literalnym fałszu (oczekiwanie "a") Co jest nie tak z moim kodem?Jak dostosować wyjście kodowania JSON w programie Go?

package main 

import (
    "bytes" 
    "encoding/json" 
    "fmt" 
    "log" 
) 

type Info struct { 
    name string 
    flag bool 
} 

func (i Info) MarshalJSON() ([]byte, error) { 
    var b bytes.Buffer 
    b.Write([]byte(i.name)) 
    if i.flag { 
     b.Write([]byte(`"true"`)) 
    } else { 
     b.Write([]byte(`"false"`)) 
    } 
    return b.Bytes(), nil 
} 

func main() { 
    a := []Info{ 
     {"foo", true}, 
     {"bar", false}, 
    } 
    out, err := json.Marshal(a) 
    if err != nil { 
     log.Fatal(err) 
    } 
    fmt.Printf(string(out)) 
} 

Odpowiedz

0

Pisanie własnych ciągów do bufora eliminuje cel json.Marshal(). Może coś takiego:

type Info struct { 
    Name string `json:"name"` // Struct fields should have capital first letter 
           // if you want it to be found by the marshaller. 
    Flag bool `json:"flag"` // json:"flag" assigns the object key in json format 
} 

a potem coś takiego:

myInfo := Info { 
    Name: "Foo", 
    Flag: true, 
} 
slc, _ := json.Marshal(myInfo) 
fmt.Println(string(slc)) 
2

Twój kod powoduje nieprawidłowy tekst JSON.

Należy napisać nazwy pól też i dla bezpieczeństwa cytatem obie nazwy pól i string wartości ale nie zacytować bool wartości (inny pakiet Go json nie unmarshal go do bool na przykład). Również załączyć swoje wartości w nawiasach {} tak:

b.Write([]byte(`{"name":"`))  // started with { 
b.Write([]byte(i.name)) 
b.Write([]byte(`","flag":`))  // note the , between values 
if i.flag { 
    b.Write([]byte(`true`))  // don't quote boolean value 
} else { 
    b.Write([]byte(`false`))  // don't quote boolean value 
} 
b.Write([]byte(`}`))    // must close with } 

Wyjście (spróbuj kompletny wniosek o Go Playground):

[{"name":"foo","flag":true},{"name":"bar","flag":false}] 

Ale skoro nie robisz niczego specjalnego podczas marszałka, tylko wyeksportuj pola (uruchamiając je dużymi literami), a pakiet json automatycznie zaatakuje je/wyrzuci automatycznie:

type Info struct { 
    Name string 
    Flag bool 
} 

Wypróbuj tę wersję na Go Playground.

Wyjście (nota górnym bocznym nazwy "Name" i "Flag"):

[{"Name":"foo","Flag":true},{"Name":"bar","Flag":false}] 

Można również używać znaczników jeśli chcesz używać różnych nazw w tekście JSON jak poniżej:

type Info struct { 
    Name string `json:"name"` 
    Flag bool `json:"flag"` 
} 

Spowoduje to ponowne wygenerowanie danych wyjściowych o nazwach pisanych małymi literami:

[{"name":"foo","flag":true},{"name":"bar","flag":false}] 

Przeczytaj dokumentację funkcji json.Marshal(), aby dowiedzieć się, jakie inne opcje i dostosowania można wykonać za pomocą znaczników struct.

+0

Och, myślałem, że mógłbym wydać Marszałek, czego chcę, nawet nielegalny tekst JSON – Meng

+1

@Meng To nie nazywa się JSON marshaling, to się nazywa generowanie _na_ binarnej/treści tekstowej. – icza

0

Problem polega na tym, że w ramach wdrożenia MarshalJSON oczekuje się bardzo dużo magii. Niestety, musisz spojrzeć na to tak, jakby budowałeś strunę całkowicie od zera. To znaczy;

func (i Info) MarshalJSON() ([]byte, error) { 
    var b bytes.Buffer 
    b.Write([]byte(i.name)) 
    if i.flag { 
     b.Write([]byte(`"true"`)) 
    } else { 
     b.Write([]byte(`"false"`)) 
    } 
    return b.Bytes(), nil 
} 

Potrzebuje wyglądać bardziej jak to;

func (i Info) MarshalJSON() ([]byte, error) { 
    var b bytes.Buffer 
    b.Write([]byte(`{"name":"`))  
    b.Write([]byte(i.name)) 
    b.Write([]byte(`","flag":`))   
    if i.flag { 
     b.Write([]byte(`"true"`))   
    } else { 
     b.Write([]byte(`"false"`))  
    } 
    b.Write([]byte(`}`)) 
} 

Ponadto, zakładam, że zgodnie z prawem chcesz ciąg znaków dla wartości logicznych (w przeciwnym razie, dlaczego zaimplementować tę metodę w ogóle, prawda?), jeśli nie, to będziesz chciał pozbyć się tego i po prostu użyć b.Write([]byte(i.flag)).

Powiązane problemy