尝试解组一个 map[Priority]string。

huangapple go评论83阅读模式
英文:

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

AniSkywalkerputu在评论中提到的,你可以实现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)) }

huangapple
  • 本文由 发表于 2017年6月12日 04:35:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/44488526.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定