试图解组地图[优先级]字符串

时间:2017-06-11 20:35:59

标签: json go unmarshalling

我一直在使用Golang json软件包,并且遇到了一个问题,我只是试图以最简单的方式将map[string]string解组为map[Priority]string,但似乎我的UnmarshalJSON不是甚至运行,以下是我的代码,我想做一个可以运行的游乐场,但我正在使用操作系统包:

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方法,并且我不知道这是否是它的假设工作方式,因为我已经嵌套了地图内的优先级类型。

所以我也许我必须为整个地图做一个别名类型,如:

type FGColor map[Priority]string 

并实现unmarshal而不是,但这似乎不合逻辑,因为嵌套的结构将是我想的unmarshal的噩梦。

我做错了什么?

2 个答案:

答案 0 :(得分: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"
)

答案 1 :(得分: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))

}