我想在JSON文件中存储自定义调色板,但是调色板的类型为[]color.Color
(这是一个接口,而不是具体的类型)。当我整理调色板时,我得到的是这样的:
[{"R":0,"G":0,"B":0,"A":255},{"R":0,"G":0,"B":51,"A":255}...]
问题是,当我解组JSON时,类型[]color.Color
不起作用,因为Go无法在该接口下创建具体类型。
我已将代码简化为以下示例:
type myT struct {
P []color.Color
}
func main() {
t := myT{palette.WebSafe}
b, err := json.Marshal(t)
e("json.Marshal", err)
t2 := myT{}
err = json.Unmarshal(b, &t2)
e("json.Unmarshal", err)
fmt.Println(string(b))
}
func e(s string, err error) {
if err != nil {
fmt.Println(s, err)
}
}
https://play.golang.org/p/QYIpJ7L1ete
是否有一个简单的解决方案,还是必须将[]color.Color
转换为[]color.RGBA
?
答案 0 :(得分:1)
我会听从Tim的建议,并开始使用color.RGBA,但是如果您对如何为自定义类型实现自定义UnmarshalJSON函数感兴趣,我将在下面和此处概述代码:https://play.golang.org/p/8p5a09993GV
基本上,您可以使用UnmarshalJSON函数作为中间层来解码为“正确的” RGBA类型,然后进行一些类型转换,以使其成为您想要的自定义myT类型的接口。
同样,在整个实现中使用color.RGBA代替color.Color可能会更容易,但这是您如何将其转换。
这里有一个精要的要点: https://gist.github.com/mdwhatcott/8dd2eef0042f7f1c0cd8
gopher学院的博客文章,确实做了一些有趣的事情: https://blog.gopheracademy.com/advent-2016/advanced-encoding-decoding/
很好地解释了为什么[]struct
与它可能实现的[]interface
不1/1匹配:
golang: slice of struct != slice of interface it implements?
package main
import (
"encoding/json"
"fmt"
"image/color"
"image/color/palette"
)
type myT struct {
P []color.Color
}
func main() {
t := myT{palette.WebSafe}
b, err := json.Marshal(t)
e("json.Marshal", err)
t2 := myT{}
err = json.Unmarshal(b, &t2)
e("json.Unmarshal", err)
fmt.Println(string(b))
fmt.Println(string(t2))
}
func e(s string, err error) {
if err != nil {
fmt.Println(s, err)
}
}
func (myt *myT) UnmarshalJSON(b []byte) error {
var tempJson struct {
P []color.RGBA
}
// Unmarshal to our temp struct
err := json.Unmarshal(b, &tempJson)
if err != nil {
return err
}
// convert our new friends O(n) to the interface type
newColors := make([]color.Color, len(tempJson.P))
for i, v := range tempJson.P {
newColors[i] = color.Color(v)
}
myt.P = newColors
return nil
}