Jeste li ikada morali modificirati nestrukturirane JSON podatke u Go? Možda ste morali izbrisati lozinku i sva polja s crne liste, preimenovati ključeve iz camelCase
u snake_case
ili pretvoriti sve ID-ove brojeva u nizove jer JavaScript ne voli int64
? Ako je vaše rješenje bilo demarširati sve u map[string]any
pomoću encoding/json
i zatim to marširati natrag... pa, budimo iskreni, to je daleko od učinkovitog!
Što ako možete proći kroz JSON podatke, uhvatiti putanju svake stavke i odlučiti točno što ćete s njom u hodu?
Da! Imam dobre vijesti! S novom značajkom iteratora u Go 1.23, postoji bolji način za ponavljanje i manipuliranje JSON-om. Upoznajte ezpkg.io/iter.json — vašeg moćnog i učinkovitog suputnika za rad s JSON-om u Go-u.
S obzirom da imamo datoteku alice.json :
{ "name": "Alice", "age": 24, "scores": [9, 10, 8], "address": { "city": "The Sun", "zip": 10101 } }
Prvo, upotrijebimo for range Parse()
za iteraciju po JSON datoteci, a zatim ispišite putanju, ključ, token i razinu svake stavke. Vidi primjere/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) } }
Kod će ispisati:
| 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 |
Koristite Builder
za izradu JSON podataka. Prihvaća neobavezne argumente za uvlačenje. Vidi primjere/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", "[email protected]") 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)
Što će ispisati JSON s uvlakom:
{ "name": "Alice", "age": 22, "email": "[email protected]", "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 } ] }
Možete rekonstruirati ili formatirati JSON podatke slanjem ključa i vrijednosti Builder
u. Vidi primjere/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) }
Prvi primjer minimizira JSON dok ga drugi primjer formatira s prefiksom "👉" u svakom retku.
--- 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 👉 } 👉 } ----------
U ovom primjeru JSON izlazu dodajemo brojeve redaka dodavanjem b.WriteNewline()
prije poziva fmt.Fprintf()
. Vidi examples/04.line_number .
// 🐞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)
Ovo će ispisati:
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 }
Stavljanjem fmt.Fprintf(comment)
između b.WriteComma()
i b.WriteNewline()
, možete dodati komentar na kraj svakog retka. Vidi examples/05.comment .
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)
Ovo će ispisati:
{ // 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
Postoje item.GetPathString()
i item.GetRawPath()
za dobivanje putanje trenutne stavke. Možete ih koristiti za filtriranje JSON podataka. Pogledajte primjere/06.filter_print .
Primjer s item.GetPathString()
i 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()) }
Primjer s item.GetRawPath()
i 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()) }
Oba će primjera ispisati:
2 "Alice" . name 9 { . address 10 "The Sun" . address.city 11 10101 . address.zip 12 } . address
Kombiniranjem Builder
s opcijom SetSkipEmptyStructures(false)
i logikom filtriranja, možete filtrirati JSON podatke i vratiti novi JSON. Pogledajte primjere/07.filter_json
// 🦁Example: filter and output json b := iterjson.NewBuilder("", " ") b.SetSkipEmptyStructures(true) // 👉 skip empty [] or {} for item, err := range iterjson.Parse(data) { errorz.MustZ(err) if item.Token.IsOpen() || item.Token.IsClose() { b.Add(item.Key, item.Token) continue } path := item.GetPathString() switch { case path == "name", strings.Contains(path, "address"): // continue default: continue } b.Add(item.Key, item.Token) } out := errorz.Must(b.Bytes()) fmt.Printf("\n--- filter: output json ---\n%s\n----------\n", out)
Ovaj će primjer vratiti novi JSON samo s filtriranim poljima:
{ "name": "Alice", "address": { "city": "The Sun", "zip": 10101 } }
Ovo je primjer za uređivanje vrijednosti u JSON podacima. Pretpostavimo da koristimo identifikacijske brojeve brojeva za naš API. ID-ovi su preveliki i JavaScript ih ne može obraditi. Moramo ih pretvoriti u nizove. Pogledajte examples/08.number_id i order.json .
Iterirajte JSON podatke, pronađite sva _id
polja i pretvorite brojeve ID-ova u nizove:
b := iterjson.NewBuilder("", " ") for item, err := range iterjson.Parse(data) { errorz.MustZ(err) key, _ := item.GetRawPath().Last().ObjectKey() if strings.HasSuffix(key, "_id") { id, err0 := item.Token.GetInt() if err0 == nil { b.Add(item.Key, strconv.Itoa(id)) continue } } b.Add(item.Key, item.Token) } out := errorz.Must(b.Bytes()) fmt.Printf("\n--- convert number id ---\n%s\n----------\n", out)
Ovo će dodati navodnike ID-ovima brojeva:
{ "order_id": "12345678901234", "number": 12, "customer_id": "12345678905678", "items": [ { "item_id": "12345678901042", "quantity": 1, "price": 123.45 }, { "item_id": "12345678901098", "quantity": 2, "price": 234.56 } ] }
Paket ezpkg.io/iter.json omogućuje Go programerima da precizno i učinkovito rukuju JSON podacima. Bilo da trebate iterirati kroz složene JSON strukture, dinamički graditi nove JSON objekte, formatirati ili minimizirati podatke, filtrirati određena polja ili čak transformirati vrijednosti, iter.json nudi fleksibilno i snažno rješenje.
Uzbuđen sam što mogu sa zajednicom podijeliti ovaj paket kao alat za učinkovitu manipulaciju JSON-om bez potrebe za potpunim analiziranjem podataka. Iako je još uvijek u ranom razvoju i ima mjesta za više značajki, već dobro radi u mnogim uobičajenim slučajevima upotrebe.
Ako imate specifične zahtjeve ili ideje za poboljšanje, slobodno se obratite — volio bih čuti vaše povratne informacije i pomoći u vašim slučajevima upotrebe! 🥳
Ja sam Oliver Nguyen. Softverski inženjer koji radi s Go i JS. Uživam učiti i vidjeti bolju verziju sebe svaki dan. Povremeno pokrenuti nove projekte otvorenog koda. Dijelite znanje i misli tijekom mog putovanja.
Post je također objavljen na