如何在Go中将调色板调配和解编为JSON?

时间:2018-11-21 19:42:06

标签: json go

我想在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

1 个答案:

答案 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
}