While coding with Go, I had to convert something like a bidirectional list to my own & JSON. The policy is to use ʻencoding / json`, but it's a mess.
json:"-" and stop itIt's a matter of course.
package main
import (
	"encoding/json"
	"fmt"
	"log"
)
type Person struct {
	Name   string
	Parent Person
	Child  Person
}
func main() {
	sora := Person{}
	sora.Name = "Sora Amamiya"
	j, err := json.Marshal(sora)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(j))
}
I get angry like this.
$ go run main.go
# command-line-arguments
./main.go:9:6: invalid recursive type Person
That's right. It seems that they get angry even with mutual recursion. excellence.
Solved by fixing it to a pointer.
package main
import (
	"encoding/json"
	"fmt"
	"log"
)
type Person struct {
	Name   string
	Parent *Person
	Child  *Person
}
func main() {
	sora := Person{}
	sora.Name = "Sora Amamiya"
	j, err := json.Marshal(sora)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(j))
}
$ go run main.go
{"Name":"Sora Amamiya","Parent":null,"Child":null}
This is the main subject. I'm wondering how often I want to turn a bidirectional list into JSON in the first place.
The structure of Person is the same as before. Make a small bidirectional list like this.

package main
import (
	"encoding/json"
	"fmt"
	"log"
)
type Person struct {
	Name   string  `json:"name"`
	Parent *Person 
	Child  *Person `json:"child"`
}
func main() {
	m := Person{}
	n := Person{}
	m.Name = "Momo Asakura"
	m.Child = &n
	n.Name = "Shiina Natsukawa"
	n.Parent = &m
	j, err := json.Marshal([]Person{m, n})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(j))
}
The output is literally endlessly angry like this. It's a recursive error.
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
runtime stack:
runtime.throw(0x4f30b2, 0xe)
        /usr/local/go/src/runtime/panic.go:774 +0x72
runtime.newstack()
        /usr/local/go/src/runtime/stack.go:1046 +0x6e9
runtime.morestack()
        /usr/local/go/src/runtime/asm_amd64.s:449 +0x8f
goroutine 1 [running]:
encoding/json.stringEncoder(0xc00007c000, 0x4c8f80, 0xc00000c080, 0x198, 0x100)
        /usr/local/go/src/encoding/json/encode.go:589 +0x389 fp=0xc02009a380 sp=0xc02009a378 pc=0x4a94c9
encoding/json.structEncoder.encode(0xc000082000, 0x3, 0x4, 0xc00005e2a0, 0xc00007c000, 0x4dcee0, 0xc00000c
That's quite natural. It's no good to have a shallow idea, "If you don't attach a JSON tag to Parent, can you ignore Wanchan?" By default, the field name is used as it is and converted. A very good library.
So what I wanted to do was "ignore arbitrary fields in the JSON library".
To do this, use the tag json:"-".
package main
import (
	"encoding/json"
	"fmt"
	"log"
)
type Person struct {
	Name   string  `json:"name"`
	Parent *Person `json:"-"`
	Child  *Person `json:"child"`
}
func main() {
	m := Person{}
	n := Person{}
	m.Name = "Momo Asakura"
	m.Child = &n
	n.Name = "Shiina Natsukawa"
	n.Parent = &m
	j, err := json.Marshal([]Person{m, n})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(j))
}
Click here for the output result. He brings only Child properly. If you pull from Root, you don't need to put out Parent separately.
$ go run main.go
[{"name":"Momo Asakura","child":{"name":"Shiina Natsukawa","child":null}},{"name":"Shiina Natsukawa","chil
d":null}]
Recommended Posts