2015-04-21 5 views
5

Ich möchte Codierung Format einer Struktur anpassen, aber Fehler: Json: Fehler beim Aufrufen von MarshalJSON für den Typ main.Info: ungültiges Zeichen 'o' in Literal false (erwartet 'a') Was ist falsch mit meinem Code?Wie wird die JSON-Kodierungsausgabe in Go angepasst?

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)) 
} 

Antwort

0

Schreiben Sie Ihre eigenen Zeichenketten in einen Puffer eliminiert Art den Zweck json.Marshal(). Vielleicht so etwas wie:

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 
} 

Und dann so etwas wie:

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

Ihr Code erzeugt ungültigen JSON Text.

Sie sollten die Namen der Felder zu, und für die Sicherheit Zitat sowohl die Feldnamen und string Werte aber zitiert nicht bool Werte (sonst die Go json Paket wird es nicht in bool zum Beispiel entpacken) schreiben. Auch Ihre Werte in Klammern {} wie folgt einschließen:

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 } 

Output (versuchen Sie die vollständige Anwendung auf dem Go Playground):

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

Aber da du nichts Besonderes während Marschall tun, nur Exportieren Sie die Felder (indem Sie sie mit Großbuchstaben beginnen) und das json-Paket marshallt/entmarshallt es für Sie automatisch:

type Info struct { 
    Name string 
    Flag bool 
} 

Versuchen Sie diese Version auf der Go Playground.

Ausgang (man beachte die in Großbuchstaben Namen "Name" und "Flag"):

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

Sie können auch Tags verwenden, wenn Sie verschiedene Namen im JSON-Text wie diese verwenden möchten:

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

Dies wird wieder einen Ausgang mit niedrigeren Namen erzeugen:

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

Lesen Sie die Dokumentation der json.Marshal()-Funktion, um zu sehen, welche anderen Optionen und Anpassungen Sie mit Strukturtags vornehmen können.

+0

Oh, ich habe gedacht, dass ich Marshal heraus, was auch immer ich will, auch illegale JSON Text – Meng

+1

@Meng Das heißt nicht JSON Marshalling, das heißt die Generierung _any_ binary/Text Inhalt. – icza

0

Das Problem ist, dass Sie eine Menge erwarten magisch passieren für Sie innerhalb Ihrer Implementierung von MarshalJSON. Leider müssen Sie es so betrachten, als würden Sie die Saite komplett neu aufbauen. Bedeutung dies;

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 
} 

Muss eher so aussehen;

Auch ich nehme an, dass Sie legitimerweise eine Zeichenfolge für die booleschen Werte wünschen (sonst warum diese Methode überhaupt implementieren, oder?), wenn nicht, dann sollten Sie das if loswerden und einfach b.Write([]byte(i.flag)) verwenden.

Verwandte Themen