英文:
Trying to Unmarshal a map[Priority]string
问题
我一直在尝试使用Golang的json包,并遇到了一个问题。我只是简单地尝试将map[string]string
解析为map[Priority]string
,但似乎我的UnmarshalJSON方法甚至没有运行。以下是我的代码,我本来想创建一个可以运行的playground,但我正在使用OS包,所以无法创建文件:
import (
"encoding/json"
"fmt"
"os"
)
type Priority int
const (
VERYLOW = Priority(iota)
LOW
MEDIUM
HIGH
VERYHIGH
)
const (
verylow = "verylow"
low = "low"
medium = "medium"
high = "high"
veryhigh = "veryhigh"
// ANSI color constants.
RESET = "\x1b[0m"
BRIGHT = "\x1b[1m"
DIM = "\x1b[2m"
UNDERSCORE = "\x1b[4m"
BLINK = "\x1b[5m"
REVERSE = "\x1b[7m"
HIDDEN = "\x1b[8m"
FGBLACK = "\x1b[30m"
FGRED = "\x1b[31m"
FGGREEN = "\x1b[32m"
FGYELLOW = "\x1b[33m"
FGBLUE = "\x1b[34m"
FGMAGENTA = "\x1b[35m"
FGCYAN = "\x1b[36m"
FGWHITE = "\x1b[37m"
BGBLACK = "\x1b[40m"
BGRED = "\x1b[41m"
BGGREEN = "\x1b[42m"
BGYELLOW = "\x1b[43m"
BGBLUE = "\x1b[44m"
BGMAGENTA = "\x1b[45m"
BGCYAN = "\x1b[46m"
BGWHITE = "\x1b[47m"
TITLE_COLOUR = BRIGHT + FGGREEN
NUMBER_COLOR = FGGREEN
//color constants
BLACK = "BLACK"
RED = "RED"
GREEN = "GREEN"
YELLOW = "YELLOW"
BLUE = "BLUE"
MAGENTA = "MAGENTA"
CYAN = "CYAN"
WHITE = "WHITE"
BRIGHTBLACK = "BRIGHTBLACK"
BRIGHTRED = "BRIGHTRED"
BRIGHTGREEN = "BRIGHTGREEN"
BRIGHTYELLOW = "BRIGHTYELLOW"
BRIGHTBLUE = "BRIGHTBLUE"
BRIGHTMAGENTA = "BRIGHTMAGENTA"
BRIGHTCYAN = "BRIGHTCYAN"
BRIGHTWHITE = "BRIGHTWHITE"
NOCOLOR = ""
)
type Config struct {
Name string
FGColors map[Priority]string
}
type MarshalableConfig struct {
Name string
FGColors map[string]string
}
var priorityMapFromString = map[string]Priority{
veryhigh: VERYHIGH,
high: HIGH,
medium: MEDIUM,
low: LOW,
verylow: VERYLOW,
}
var priorityToString = map[Priority]string{
VERYHIGH: veryhigh,
HIGH: high,
MEDIUM: medium,
VERYLOW: verylow,
LOW: low,
}
func (p Priority) String() string {
return priorityToString[p]
}
func PriorityFromString(priority string) Priority {
if p, ok := priorityMapFromString[priority]; ok {
return p
}
return MEDIUM
}
func (priority *Priority) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*priority = PriorityFromString(s)
return nil
}
func main() {
fgColors := map[string]string{
verylow: RED,
low: BLUE,
medium: GREEN,
high: BRIGHTBLUE,
veryhigh: BRIGHTMAGENTA,
}
m := MarshalableConfig{"Alice", fgColors}
b, err := json.Marshal(m)
if err != nil {
panic(err)
}
file, err := os.Create("testfile.json")
if err != nil {
panic(err)
}
file.Write(b)
emptyConfig := Config{}
err = json.Unmarshal(b, &emptyConfig)
if err != nil {
fmt.Printf("Got a error from unmarshalling: %+v \n", err)
panic(err)
}
fmt.Printf("%+v \n", emptyConfig)
var x interface{} = emptyConfig.FGColors[VERYHIGH]
fmt.Println(x.(string))
}
我得到以下错误:
json: cannot unmarshal number high into Go value of type main.Priority
所以我得到的印象是它从未调用我的UnmarshalJSON方法来处理优先级,而且我不知道是否应该这样工作,因为我现在将Priority类型嵌套在map中。所以我想也许我需要为整个map创建一个别名类型,像这样:
type FGColor map[Priority]string
然后在该类型上实现unmarshal,但这似乎不合逻辑,因为嵌套的结构将很难解析。
我做错了什么?
英文:
I have been playing around with the Golang json package, and been running into a issue, i am simply trying to unmarshal a map[string]string
into map[Priority]string
the easiest way, but it seems like my UnmarshalJSON isn't even running, the following is my code, i would've like to made a playground where it could run, but i am using the OS package so:
import (
"encoding/json"
"fmt"
"os"
)
type Priority int
const (
VERYLOW = Priority(iota)
LOW
MEDIUM
HIGH
VERYHIGH
)
const (
verylow = "verylow"
low = "low"
medium = "medium"
high = "high"
veryhigh = "veryhigh"
// ANSI color constants.
RESET = "\x1b[0m"
BRIGHT = "\x1b[1m"
DIM = "\x1b[2m"
UNDERSCORE = "\x1b[4m"
BLINK = "\x1b[5m"
REVERSE = "\x1b[7m"
HIDDEN = "\x1b[8m"
FGBLACK = "\x1b[30m"
FGRED = "\x1b[31m"
FGGREEN = "\x1b[32m"
FGYELLOW = "\x1b[33m"
FGBLUE = "\x1b[34m"
FGMAGENTA = "\x1b[35m"
FGCYAN = "\x1b[36m"
FGWHITE = "\x1b[37m"
BGBLACK = "\x1b[40m"
BGRED = "\x1b[41m"
BGGREEN = "\x1b[42m"
BGYELLOW = "\x1b[43m"
BGBLUE = "\x1b[44m"
BGMAGENTA = "\x1b[45m"
BGCYAN = "\x1b[46m"
BGWHITE = "\x1b[47m"
TITLE_COLOUR = BRIGHT + FGGREEN
NUMBER_COLOR = FGGREEN
//color constants
BLACK = "BLACK"
RED = "RED"
GREEN = "GREEN"
YELLOW = "YELLOW"
BLUE = "BLUE"
MAGENTA = "MAGENTA"
CYAN = "CYAN"
WHITE = "WHITE"
BRIGHTBLACK = "BRIGHTBLACK"
BRIGHTRED = "BRIGHTRED"
BRIGHTGREEN = "BRIGHTGREEN"
BRIGHTYELLOW = "BRIGHTYELLOW"
BRIGHTBLUE = "BRIGHTBLUE"
BRIGHTMAGENTA = "BRIGHTMAGENTA"
BRIGHTCYAN = "BRIGHTCYAN"
BRIGHTWHITE = "BRIGHTWHITE"
NOCOLOR = ""
)
type Config struct {
Name string
FGColors map[Priority]string
}
type MarshalableConfig struct {
Name string
FGColors map[string]string
}
var priorityMapFromString = map[string]Priority{
veryhigh: VERYHIGH,
high: HIGH,
medium: MEDIUM,
low: LOW,
verylow: VERYLOW,
}
var priorityToString = map[Priority]string{
VERYHIGH: veryhigh,
HIGH: high,
MEDIUM: medium,
VERYLOW: verylow,
LOW: low,
}
func (p Priority) String() string {
return priorityToString
}
func PriorityFromString(priority string) Priority {
if p, ok := priorityMapFromString[priority]; ok {
return p
}
return MEDIUM
}
func (priority *Priority) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*priority = PriorityFromString(s)
return nil
}
func main() {
fgColors := map[string]string{
verylow: RED,
low: BLUE,
medium: GREEN,
high: BRIGHTBLUE,
veryhigh: BRIGHTMAGENTA,
}
m := MarshalableConfig{"Alice", fgColors}
b, err := json.Marshal(m)
if err != nil {
panic(err)
}
file, err := os.Create("testfile.json")
if err != nil {
panic(err)
}
file.Write(b)
emptyConfig := Config{}
err = json.Unmarshal(b, &emptyConfig)
if err != nil {
fmt.Printf("Got a error from unmarshalling: %+v \n", err)
panic(err)
}
fmt.Printf("%+v \n", emptyConfig)
var x interface{} = emptyConfig.FGColors[VERYHIGH]
fmt.Println(x.(string))
}
I get the error:
json: cannot unmarshal number high into Go value of type main.Priority
So the impression i get is that it never calls my UnmarshalJSON method on the priority, and i don't know if thats the way its suppose to work anyway now that i have nested the Priority type inside of the map.
So i thouth maybe i have to do a alias type for the whole map like:
type FGColor map[Priority]string
and implement unmarshal on that instead, but that doesn't seem logical, because nested structs would be a nightmare to unmarshal i would think.
What am i doing wrong??
答案1
得分: 1
如AniSkywalker
和putu
在评论中提到的,你可以实现encoding.TextUnmarshaler
。
然而,在你的情况下,由于你需要将Priority
用作JSON映射键,所以更容易的方法是将Priority
定义为字符串类型。
type Priority string
const (
VERYLOW = "verylow"
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
VERYHIGH = "veryhigh"
)
这样,你也可以放弃使用以下内容。
const (
verylow = "verylow"
low = "low"
medium = "medium"
high = "high"
veryhigh = "veryhigh"
)
英文:
As AniSkywalker
and putu
have mentioned in the comments, you could impliment encoding.TextUnmarshaler
.
However I think in your case since you need to use Priority
as a json map key, it's much easier to just use Priority as a type string.
type Priority string
const (
VERYLOW = "verylow"
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
VERYHIGH = "veryhigh" )
This way you can discard the use of the following as well.
const (
verylow = "verylow"
low = "low"
medium = "medium"
high = "high"
veryhigh = "veryhigh"
)
答案2
得分: 0
我根据@AniSkywalker的评论更新了代码,使用UnmarshalText函数,以下是更新后的代码:
package main
import (
"encoding/json"
"fmt"
)
type Priority int
const (
VERYLOW = Priority(iota)
LOW
MEDIUM
HIGH
VERYHIGH
)
const (
verylow = "verylow"
low = "low"
medium = "medium"
high = "high"
veryhigh = "veryhigh"
// ANSI color constants.
RESET = "\x1b[0m"
BRIGHT = "\x1b[1m"
DIM = "\x1b[2m"
UNDERSCORE = "\x1b[4m"
BLINK = "\x1b[5m"
REVERSE = "\x1b[7m"
HIDDEN = "\x1b[8m"
FGBLACK = "\x1b[30m"
FGRED = "\x1b[31m"
FGGREEN = "\x1b[32m"
FGYELLOW = "\x1b[33m"
FGBLUE = "\x1b[34m"
FGMAGENTA = "\x1b[35m"
FGCYAN = "\x1b[36m"
FGWHITE = "\x1b[37m"
BGBLACK = "\x1b[40m"
BGRED = "\x1b[41m"
BGGREEN = "\x1b[42m"
BGYELLOW = "\x1b[43m"
BGBLUE = "\x1b[44m"
BGMAGENTA = "\x1b[45m"
BGCYAN = "\x1b[46m"
BGWHITE = "\x1b[47m"
TITLE_COLOUR = BRIGHT + FGGREEN
NUMBER_COLOR = FGGREEN
//color constants
BLACK = "BLACK"
RED = "RED"
GREEN = "GREEN"
YELLOW = "YELLOW"
BLUE = "BLUE"
MAGENTA = "MAGENTA"
CYAN = "CYAN"
WHITE = "WHITE"
BRIGHTBLACK = "BRIGHTBLACK"
BRIGHTRED = "BRIGHTRED"
BRIGHTGREEN = "BRIGHTGREEN"
BRIGHTYELLOW = "BRIGHTYELLOW"
BRIGHTBLUE = "BRIGHTBLUE"
BRIGHTMAGENTA = "BRIGHTMAGENTA"
BRIGHTCYAN = "BRIGHTCYAN"
BRIGHTWHITE = "BRIGHTWHITE"
NOCOLOR = ""
)
type Config struct {
Name string
FGColors map[Priority]string
}
type MarshalableConfig struct {
Name string
FGColors map[string]string
}
var priorityMapFromString = map[string]Priority{
veryhigh: VERYHIGH,
high: HIGH,
medium: MEDIUM,
low: LOW,
verylow: VERYLOW,
}
var priorityToString = map[Priority]string{
VERYHIGH: veryhigh,
HIGH: high,
MEDIUM: medium,
VERYLOW: verylow,
LOW: low,
}
func (p Priority) String() string {
return priorityToString[p]
}
func PriorityFromString(priority string) Priority {
if p, ok := priorityMapFromString[priority]; ok {
return p
}
return MEDIUM
}
func (priority *Priority) UnmarshalText(data []byte) error {
*priority = PriorityFromString(string(data))
return nil
}
func main() {
fgColors := map[string]string{
verylow: RED,
low: BLUE,
medium: GREEN,
high: BRIGHTBLUE,
veryhigh: BRIGHTMAGENTA,
}
m := MarshalableConfig{"Alice", fgColors}
b, err := json.Marshal(m)
if err != nil {
panic(err)
}
emptyConfig := Config{}
err = json.Unmarshal(b, &emptyConfig)
if err != nil {
fmt.Printf("Got a error from unmarshalling: %+v \n", err)
panic(err)
}
fmt.Printf("%+v \n", emptyConfig)
var x interface{} = emptyConfig.FGColors[VERYHIGH]
fmt.Println(x.(string))
}
英文:
I updated my code, as per the comment from @AniSkywalker to the following code, using the UnmarshalText:
package main
import (
"encoding/json"
"fmt"
)
type Priority int
const (
VERYLOW = Priority(iota)
LOW
MEDIUM
HIGH
VERYHIGH
)
const (
verylow = "verylow"
low = "low"
medium = "medium"
high = "high"
veryhigh = "veryhigh"
// ANSI color constants.
RESET = "\x1b[0m"
BRIGHT = "\x1b[1m"
DIM = "\x1b[2m"
UNDERSCORE = "\x1b[4m"
BLINK = "\x1b[5m"
REVERSE = "\x1b[7m"
HIDDEN = "\x1b[8m"
FGBLACK = "\x1b[30m"
FGRED = "\x1b[31m"
FGGREEN = "\x1b[32m"
FGYELLOW = "\x1b[33m"
FGBLUE = "\x1b[34m"
FGMAGENTA = "\x1b[35m"
FGCYAN = "\x1b[36m"
FGWHITE = "\x1b[37m"
BGBLACK = "\x1b[40m"
BGRED = "\x1b[41m"
BGGREEN = "\x1b[42m"
BGYELLOW = "\x1b[43m"
BGBLUE = "\x1b[44m"
BGMAGENTA = "\x1b[45m"
BGCYAN = "\x1b[46m"
BGWHITE = "\x1b[47m"
TITLE_COLOUR = BRIGHT + FGGREEN
NUMBER_COLOR = FGGREEN
//color constants
BLACK = "BLACK"
RED = "RED"
GREEN = "GREEN"
YELLOW = "YELLOW"
BLUE = "BLUE"
MAGENTA = "MAGENTA"
CYAN = "CYAN"
WHITE = "WHITE"
BRIGHTBLACK = "BRIGHTBLACK"
BRIGHTRED = "BRIGHTRED"
BRIGHTGREEN = "BRIGHTGREEN"
BRIGHTYELLOW = "BRIGHTYELLOW"
BRIGHTBLUE = "BRIGHTBLUE"
BRIGHTMAGENTA = "BRIGHTMAGENTA"
BRIGHTCYAN = "BRIGHTCYAN"
BRIGHTWHITE = "BRIGHTWHITE"
NOCOLOR = ""
)
type Config struct {
Name string
FGColors map[Priority]string
}
type MarshalableConfig struct {
Name string
FGColors map[string]string
}
var priorityMapFromString = map[string]Priority{
veryhigh: VERYHIGH,
high: HIGH,
medium: MEDIUM,
low: LOW,
verylow: VERYLOW,
}
var priorityToString = map[Priority]string{
VERYHIGH: veryhigh,
HIGH: high,
MEDIUM: medium,
VERYLOW: verylow,
LOW: low,
}
func (p Priority) String() string {
return priorityToString
}
func PriorityFromString(priority string) Priority {
if p, ok := priorityMapFromString[priority]; ok {
return p
}
return MEDIUM
}
func (priority *Priority) UnmarshalText(data []byte) error {
*priority = PriorityFromString(string(data))
return nil
}
func main() {
fgColors := map[string]string{
verylow: RED,
low: BLUE,
medium: GREEN,
high: BRIGHTBLUE,
veryhigh: BRIGHTMAGENTA,
}
m := MarshalableConfig{"Alice", fgColors}
b, err := json.Marshal(m)
if err != nil {
panic(err)
}
emptyConfig := Config{}
err = json.Unmarshal(b, &emptyConfig)
if err != nil {
fmt.Printf("Got a error from unmarshalling: %+v \n", err)
panic(err)
}
fmt.Printf("%+v \n", emptyConfig)
var x interface{} = emptyConfig.FGColors[VERYHIGH]
fmt.Println(x.(string))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论