为什么“ switch t:= policy.Parameter。(type)”不适用于viper.Unmarshal()

时间:2019-04-29 02:49:16

标签: go viper-go

我想从JSON解组几种类型,并使用该接口表示它与众不同的实际结构。但是,当我以interface{}的形式发送结构时,它将其转换为地图。 animal.json是:

"{"type":"cat","policies":[{"name":"kitty","parameter":{"duration":600,"percent":90}}]}"
package main

import (
    "reflect"

    log "github.com/sirupsen/logrus"
    "github.com/spf13/viper"
)

func main() {
    var err error
    animal := New()
    viper.SetConfigType("json")
    viper.SetConfigName("animal")
    viper.AddConfigPath("~/Desktop/")
    viper.AddConfigPath(".")
    if err := viper.ReadInConfig(); err != nil {
        return
    }

    if err = viper.Unmarshal(&animal); err != nil {
        return
    }
    for _, policy := range animal.Policies {
        log.Info(policy.Name)
        log.Info(policy.Parameter)
        //INFO[0000] map[duration:600 percent:90]
        log.Info(reflect.TypeOf(policy.Parameter))
        //INFO[0000] map[string]interface {}, Why is it not an interface{} and how do I get it?
        switch t := policy.Parameter.(type) {
        //why does the switch not work?
        case *CatParameter:
            log.Info("cat", t)
        case *DogParameter:
            log.Info("dog", t)
        }
    }
}

func New() *Animal {
    var animal Animal
    animal.Type = "cat"
    return &animal
}

type Animal struct {
    Type     string   `json:"type" form:"type"`
    Policies []Policy `json:"policies" form:"policies"`
}

type CatParameter struct {
    Duration int `json:"duration"`
    Percent  int `json:"percent"`
}

type DogParameter struct {
    Percent   int    `json:"percent"`
    Duration  int    `json:"duration"`
    Operation string `json:"operation"`
}

type Policy struct {
    Name      string      `json:"name"`
    Parameter interface{} `json:"parameter"`
}


1 个答案:

答案 0 :(得分:2)

这是json解组功能

如果您使用interface{}作为解码器,则interface{}的默认json对象为map[string]interface{}

您可以在这里看到它:

https://godoc.org/encoding/json#Unmarshal

bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null

因此在t := policy.Parameter.(type)中,tmap[string]interface{}

为解决问题,您可以尝试定义另一个字段来区分CatParameterDogParameter

也许:

type Policy struct {
    Name      string      `json:"name"`
    Parameter Parameter   `json:"parameter"`
}

type Parameter struct {
    Name      string `json:"name"`   // cat or dog
    Percent   int    `json:"percent,omitempty"`
    Duration  int    `json:"duration,omitempty"`
    Operation string `json:"operation,omitempty"`
}