In this example, I would be trying to load 2D scenes that contain polygons. In the code, I would have many different structs such as Circle, Square, Rectangle, Pentagon, etc.. All would share common funcs, such as Area and Perimeter. The scene itself would be stored as a slice of the interface Polygon.
Here is the code I'm using to test this:
package main
import (
"encoding/json"
"fmt"
"math"
)
type Polygon interface {
Area() float32
}
type Rectangle struct {
Base float32 `json:"base"`
Height float32 `json:"height"`
X float32 `json:"x"`
Y float32 `json:"y"`
}
func (r *Rectangle) Area() float32 {
return r.Base * r.Height
}
type Circle struct {
Radius float32 `json:"radius"`
X float32 `json:"x"`
Y float32 `json:"y"`
}
func (c *Circle) Area() float32 {
return c.Radius * c.Radius * math.Pi
}
func main() {
rect := Rectangle{Base: 10, Height: 10, X: 10, Y: 10}
circ := Circle{Radius: 10, X: 0, Y: 0}
sliceOfPolygons := make([]Polygon, 0, 2)
sliceOfPolygons = append(sliceOfPolygons, &rect, &circ)
jsonData, err := json.Marshal(sliceOfPolygons)
if err != nil {
panic(err)
}
fmt.Println(string(jsonData))
newSlice := make([]Polygon, 0)
err = json.Unmarshal(jsonData, &newSlice)
if err != nil {
panic(err)
}
}
In this example, I setup a slice of 2 polygons, marshal it and then try to unmarshal it again. The marshal-ed string is:
[{"base":10,"height":10,"x":10,"y":10},{"radius":10,"x":0,"y":0}]
But when I try to Unmarshal
it panics:
panic: json: cannot unmarshal object into Go value of type main.Polygon
If this worked it would be really useful and simple to use. I'd say that Unmarshall
can't distinguish between a Rectangle
and a Circle
from the json string so it can't possibly know what struct to build.
Is there any way to tag the struct or tell Unmarshal
how to distinguish this structs?