Mussten Sie jemals unstrukturierte JSON-Daten in Go ändern? Vielleicht mussten Sie alle auf der schwarzen Liste stehenden Felder löschen, Schlüssel von „camelCase“ in „snake_case“ umbenennen oder alle Zahlen-IDs in Zeichenfolgen umwandeln, weil JavaScript int64 nicht mag? Wenn Ihre Lösung darin bestand, alles mithilfe von „encoding/json“ in eine Map[string]any zu entmarshalieren und es dann wieder zu marsalieren … nun, seien wir ehrlich, das ist alles andere als effizient!
Was wäre, wenn Sie die JSON-Daten durchlaufen, den Pfad jedes Elements erfassen und im Handumdrehen genau entscheiden könnten, was damit geschehen soll?
Ja! Ich habe eine gute Nachricht! Mit der neuen Iteratorfunktion in Go 1.23 gibt es eine bessere Möglichkeit, JSON zu iterieren und zu bearbeiten. Lernen Sie ezpkg.io/iter.json kennen – Ihren leistungsstarken und effizienten Begleiter für die Arbeit mit JSON in Go.
Vorausgesetzt, wir haben eine alice.json-Datei:
{ "name": "Alice", "age": 24, "scores": [9, 10, 8], "address": { "city": "The Sun", "zip": 10101 } }
Zuerst verwenden wir for range Parse(), um die JSON-Datei zu durchlaufen, und geben dann den Pfad, den Schlüssel, das Token und die Ebene jedes Elements aus. Siehe Beispiele/01.iter.
package main import ( "fmt" "ezpkg.io/errorz" iterjson "ezpkg.io/iter.json" ) func main() { data := `{"name": "Alice", "age": 24, "scores": [9, 10, 8], "address": {"city": "The Sun", "zip": 10101}}` // ?Example: iterate over json fmt.Printf("| %12v | %10v | %10v |%v|\n", "PATH", "KEY", "TOKEN", "LVL") fmt.Println("| ------------ | ---------- | ---------- | - |") for item, err := range iterjson.Parse([]byte(data)) { errorz.MustZ(err) fmt.Printf("| %12v | %10v | %10v | %v |\n", item.GetPathString(), item.Key, item.Token, item.Level) } }
Der Code gibt Folgendes aus:
| PATH | KEY | TOKEN |LVL| | ------------ | ---------- | ---------- | - | | | | { | 0 | | name | "name" | "Alice" | 1 | | age | "age" | 24 | 1 | | scores | "scores" | [ | 1 | | scores.0 | | 9 | 2 | | scores.1 | | 10 | 2 | | scores.2 | | 8 | 2 | | scores | | ] | 1 | | address | "address" | { | 1 | | address.city | "city" | "The Sun" | 2 | | address.zip | "zip" | 10101 | 2 | | address | | } | 1 | | | | } | 0 |
Verwenden Sie Builder, um JSON-Daten zu erstellen. Es akzeptiert optionale Argumente für die Einrückung. Siehe examples/02.builder.
b := iterjson.NewBuilder("", " ") // open an object b.Add("", iterjson.TokenObjectOpen) // add a few fields b.Add("name", "Alice") b.Add("age", 22) b.Add("email", "alice@example.com") b.Add("phone", "(+84) 123-456-789") // open an array b.Add("languages", iterjson.TokenArrayOpen) b.Add("", "English") b.Add("", "Vietnamese") b.Add("", iterjson.TokenArrayClose) // close the array // accept any type that can marshal to json b.Add("address", Address{ HouseNumber: 42, Street: "Ly Thuong Kiet", City: "Ha Noi", Country: "Vietnam", }) // accept []byte as raw json b.Add("pets", []byte(`[{"type":"cat","name":"Kitty","age":2},{"type":"dog","name":"Yummy","age":3}]`)) // close the object b.Add("", iterjson.TokenObjectClose) out := errorz.Must(b.Bytes()) fmt.Printf("\n--- build json ---\n%s\n", out)
Das gibt den JSON mit Einrückung aus:
{ "name": "Alice", "age": 22, "email": "alice@example.com", "phone": "(+84) 123-456-789", "languages": [ "English", "Vietnamese" ], "address": {"house_number":42,"street":"Ly Thuong Kiet","city":"Ha Noi","country":"Vietnam"}, "pets": [ { "type": "cat", "name": "Kitty", "age": 2 }, { "type": "dog", "name": "Yummy", "age": 3 } ] }
Sie können JSON-Daten rekonstruieren oder formatieren, indem Sie deren Schlüssel und Werte an einen Builder senden. Siehe Beispiele/03.reformat.
{ // ?Example: minify json b := iterjson.NewBuilder("", "") for item, err := range iterjson.Parse(data) { errorz.MustZ(err) b.AddRaw(item.Key, item.Token) } out := errorz.Must(b.Bytes()) fmt.Printf("\n--- minify ---\n%s\n----------\n", out) } { // ?Example: format json b := iterjson.NewBuilder("? ", "\t") for item, err := range iterjson.Parse(data) { errorz.MustZ(err) b.AddRaw(item.Key, item.Token) } out := errorz.Must(b.Bytes()) fmt.Printf("\n--- reformat ---\n%s\n----------\n", out) }
Das erste Beispiel minimiert den JSON, während das zweite Beispiel ihn mit dem Präfix „?“ formatiert. in jeder Zeile.
--- minify --- {"name":"Alice","age":24,"scores":[9,10,8],"address":{"city":"The Sun","zip":10101}} ---------- --- reformat --- ? { ? "name": "Alice", ? "age": 24, ? "scores": [ ? 9, ? 10, ? 8 ? ], ? "address": { ? "city": "The Sun", ? "zip": 10101 ? } ? } ----------
In diesem Beispiel fügen wir der JSON-Ausgabe Zeilennummern hinzu, indem wir vor dem Aufruf von fmt.Fprintf() ein b.WriteNewline() hinzufügen. Siehe Beispiele/04.Zeilennummer.
// ?Example: print with line number i := 0 b := iterjson.NewBuilder("", " ") for item, err := range iterjson.Parse(data) { i++ errorz.MustZ(err) b.WriteNewline(item.Token.Type()) // ? add line number fmt.Fprintf(b, "%3d ", i) b.Add(item.Key, item.Token) } out := errorz.Must(b.Bytes()) fmt.Printf("\n--- line number ---\n%s\n----------\n", out)
Dies wird Folgendes ausgeben:
1 { 2 "name": "Alice", 3 "age": 24, 4 "scores": [ 5 9, 6 10, 7 8 8 ], 9 "address": { 10 "city": "The Sun", 11 "zip": 10101 12 } 13 }
Durch Einfügen eines fmt.Fprintf(comment) zwischen b.WriteComma() und b.WriteNewline() können Sie am Ende jeder Zeile einen Kommentar hinzufügen. Siehe Beispiele/05.Kommentar.
i, newlineIdx, maxIdx := 0, 0, 30 b := iterjson.NewBuilder("", " ") for item, err := range iterjson.Parse(data) { errorz.MustZ(err) b.WriteComma(item.Token.Type()) // ? add comment if i > 0 { length := b.Len() - newlineIdx fmt.Fprint(b, strings.Repeat(" ", maxIdx-length)) fmt.Fprintf(b, "// %2d", i) } i++ b.WriteNewline(item.Token.Type()) newlineIdx = b.Len() // save the newline index b.Add(item.Key, item.Token) } length := b.Len() - newlineIdx fmt.Fprint(b, strings.Repeat(" ", maxIdx-length)) fmt.Fprintf(b, "// %2d", i) out := errorz.Must(b.Bytes()) fmt.Printf("\n--- comment ---\n%s\n----------\n", out)
Dies wird Folgendes ausgeben:
{ // 1 "name": "Alice", // 2 "age": 24, // 3 "scores": [ // 4 9, // 5 10, // 6 8 // 7 ], // 8 "address": { // 9 "city": "The Sun", // 10 "zip": 10101 // 11 } // 12 } // 13
Es gibt item.GetPathString() und item.GetRawPath(), um den Pfad des aktuellen Elements abzurufen. Sie können sie zum Filtern der JSON-Daten verwenden. Siehe Beispiele/06.filter_print.
Beispiel mit item.GetPathString() und regexp:
fmt.Printf("\n--- filter: GetPathString() ---\n") i := 0 for item, err := range iterjson.Parse(data) { i++ errorz.MustZ(err) path := item.GetPathString() switch { case path == "name", strings.Contains(path, "address"): // continue default: continue } // ? print with line number fmt.Printf("%2d %20s . %s\n", i, item.Token, item.GetPath()) }
Beispiel mit item.GetRawPath() und path.Match():
fmt.Printf("\n--- filter: GetRawPath() ---\n") i := 0 for item, err := range iterjson.Parse(data) { i++ errorz.MustZ(err) path := item.GetRawPath() switch { case path.Match("name"), path.Contains("address"): // continue default: continue } // ? print with line number fmt.Printf("%2d %20s . %s\n", i, item.Token, item.GetPath()) }
Beide Beispiele geben Folgendes aus:
{ "name": "Alice", "age": 24, "scores": [9, 10, 8], "address": { "city": "The Sun", "zip": 10101 } }
Durch die Kombination des Builders mit der Option SetSkipEmptyStructures(false) und der Filterlogik können Sie die JSON-Daten filtern und ein neues JSON zurückgeben. Siehe Beispiele/07.filter_json
package main import ( "fmt" "ezpkg.io/errorz" iterjson "ezpkg.io/iter.json" ) func main() { data := `{"name": "Alice", "age": 24, "scores": [9, 10, 8], "address": {"city": "The Sun", "zip": 10101}}` // ?Example: iterate over json fmt.Printf("| %12v | %10v | %10v |%v|\n", "PATH", "KEY", "TOKEN", "LVL") fmt.Println("| ------------ | ---------- | ---------- | - |") for item, err := range iterjson.Parse([]byte(data)) { errorz.MustZ(err) fmt.Printf("| %12v | %10v | %10v | %v |\n", item.GetPathString(), item.Key, item.Token, item.Level) } }
Dieses Beispiel gibt ein neues JSON mit nur den gefilterten Feldern zurück:
| PATH | KEY | TOKEN |LVL| | ------------ | ---------- | ---------- | - | | | | { | 0 | | name | "name" | "Alice" | 1 | | age | "age" | 24 | 1 | | scores | "scores" | [ | 1 | | scores.0 | | 9 | 2 | | scores.1 | | 10 | 2 | | scores.2 | | 8 | 2 | | scores | | ] | 1 | | address | "address" | { | 1 | | address.city | "city" | "The Sun" | 2 | | address.zip | "zip" | 10101 | 2 | | address | | } | 1 | | | | } | 0 |
Dies ist ein Beispiel für die Bearbeitung von Werten in JSON-Daten. Gehen Sie davon aus, dass wir Nummern-IDs für unsere API verwenden. Die IDs sind zu groß und JavaScript kann sie nicht verarbeiten. Wir müssen sie in Strings konvertieren. Siehe Beispiele/08.number_id und order.json.
Durchlaufen Sie die JSON-Daten, finden Sie alle _id-Felder und konvertieren Sie die Nummern-IDs in Zeichenfolgen:
b := iterjson.NewBuilder("", " ") // open an object b.Add("", iterjson.TokenObjectOpen) // add a few fields b.Add("name", "Alice") b.Add("age", 22) b.Add("email", "alice@example.com") b.Add("phone", "(+84) 123-456-789") // open an array b.Add("languages", iterjson.TokenArrayOpen) b.Add("", "English") b.Add("", "Vietnamese") b.Add("", iterjson.TokenArrayClose) // close the array // accept any type that can marshal to json b.Add("address", Address{ HouseNumber: 42, Street: "Ly Thuong Kiet", City: "Ha Noi", Country: "Vietnam", }) // accept []byte as raw json b.Add("pets", []byte(`[{"type":"cat","name":"Kitty","age":2},{"type":"dog","name":"Yummy","age":3}]`)) // close the object b.Add("", iterjson.TokenObjectClose) out := errorz.Must(b.Bytes()) fmt.Printf("\n--- build json ---\n%s\n", out)
Dadurch werden Anführungszeichen zu den Nummern-IDs hinzugefügt:
{ "name": "Alice", "age": 22, "email": "alice@example.com", "phone": "(+84) 123-456-789", "languages": [ "English", "Vietnamese" ], "address": {"house_number":42,"street":"Ly Thuong Kiet","city":"Ha Noi","country":"Vietnam"}, "pets": [ { "type": "cat", "name": "Kitty", "age": 2 }, { "type": "dog", "name": "Yummy", "age": 3 } ] }
Das Paket ezpkg.io/iter.json ermöglicht Go-Entwicklern den präzisen und effizienten Umgang mit JSON-Daten. Egal, ob Sie komplexe JSON-Strukturen durchlaufen, neue JSON-Objekte dynamisch erstellen, Daten formatieren oder minimieren, bestimmte Felder filtern oder sogar Werte transformieren müssen, iter.json bietet eine flexible und leistungsstarke Lösung.
Ich freue mich, dieses Paket mit der Community als Tool zur effektiven JSON-Manipulation zu teilen, ohne dass die Daten vollständig analysiert werden müssen. Obwohl es sich noch in einem frühen Entwicklungsstadium befindet und Raum für weitere Funktionen vorhanden ist, funktioniert es für viele gängige Anwendungsfälle bereits gut.
Wenn Sie spezielle Anforderungen oder Verbesserungsvorschläge haben, können Sie sich gerne an uns wenden – ich freue mich über Ihr Feedback und die Unterstützung Ihrer Anwendungsfälle! ?
Ich bin Oliver Nguyen . Ein Softwareentwickler, der mit Go und JS arbeitet. Ich genieße es, zu lernen und jeden Tag eine bessere Version meiner selbst zu sehen. Gelegentlich Spin-off neuer Open-Source-Projekte. Teile Wissen und Gedanken während meiner Reise.
Der Beitrag wird auch auf olivernguyen.io veröffentlicht.
Das obige ist der detaillierte Inhalt voniter.json: Eine leistungsstarke und effiziente Möglichkeit, JSON in Go zu iterieren und zu bearbeiten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!