Stumble when converting bidirectional list to JSON in Go

What happened

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.

in short

invalid recursive type if you are in the struct

It's a matter of course.

Failure

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.

Success

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}

JSON circulation block

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.

image.png

Failure

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.

Success

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

Summary

Recommended Posts

Stumble when converting bidirectional list to JSON in Go
Things to note when initializing a list in Python
Convenient writing method when appending to list continuously in Python
How to not escape Japanese when dealing with json in python
Timezone specification when converting a string to datetime type in python
Scraping the list of Go To EAT member stores in Fukuoka prefecture and converting it to CSV
Post to slack in Go language
Scraping the list of Go To EAT member stores in Niigata prefecture and converting it to CSV
When creating a matrix in a list
Things to keep in mind when converting row vectors to column vectors with ndarray
What to do when a warning message is displayed in pip list
How to achieve something like a list of void * (or variant) in Go?
I got an error when trying to run Hello World in Go language
Convert PDF of list of Go To EAT member stores in Niigata prefecture to CSV
How to clear tuples in a list (Python)
How to create a JSON file in Python
I want to store DB information in list
Sample API server to receive JSON in Golang
Error when trying to install psycopg2 in Python
Use pygogo to get the log in json.
How to remove duplicate elements in Python3 list
Differences in behavior between append () and "+ =" operators when adding data to a list in Python