为了账号安全,请及时绑定邮箱和手机立即绑定

高浪如何接受不确定的价值观

高浪如何接受不确定的价值观

Go
幕布斯6054654 2022-09-19 17:39:09
后端返回值不是固定的,有时:{"application": {"instance": [{"instanceId": "v1"}, {"instanceId": "v2"}]}}或者有时:{"application": {"instance": {"instanceId": "v"}}}我应该如何取出相应的实例 Id 值?package mainimport (    "encoding/json"    "fmt")type Application struct {    Application struct {        Instance json.RawMessage `json:"instance"`    } `json:"application"`}func main() {    a := `{"application": {"instance": {"instanceId": "v"}}}`    //a := `{"application": {"instance": [{"instanceId": "v1"}, {"instanceId": "v2"}]}} `    var p Application    errJson := json.Unmarshal([]byte(a), &p)    if errJson != nil {        fmt.Printf("errJson")    }    fmt.Printf("type:%T", p.Application.Instance)}
查看完整描述

2 回答

?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

由于 2 种值类型发生冲突(一种是结构,另一种是结构的一部分),因此即使使用捕获所有解决方案(如 ),将其封装到单个类型中也会变得很混乱。interface{}


最简单的解决方案是呈现两种不同的类型并封送到其中任何一个,以查看哪个“有效”:


func unmarsh(body []byte) (*type1, *type2, error) {

    var (

        t1 type1

        t2 type2

    )


    err := json.Unmarshal(body, &t1)

    if err == nil {

        return &t1, nil, nil

    }


    err = json.Unmarshal(body, &t2)

    if err == nil {

        return nil, &t2, nil

    }


    return nil, nil, err


}

在您的示例中,两种类型将是:


type type1 struct {

    Application struct {

        Instance []struct {

            InstanceID string `json:"instanceId"`

        } `json:"instance"`

    } `json:"application"`

}


type type2 struct {

    Application struct {

        Instance struct {

            InstanceID string `json:"instanceId"`

        } `json:"instance"`

    } `json:"application"`

}

工作示例:https://play.golang.org/p/Kma32gWfghb


查看完整回答
反对 回复 2022-09-19
?
慕的地10843

TA贡献1785条经验 获得超8个赞

一个更干净的解决方案是自定义的拆包器:


type Instances []Instance


func (i *Instances) UnmarshalJSON(in []byte) error {

   if len(in)>0 && in[0]=='[' {

     var a []Instance

     if err:=json.Unmarshal(in,&a); err!=nil {

        return err

     }

     *i=a

     return nil

  }

  var s Instance

  if err:=json.Unmarshal(in,&s) ; err!=nil {

     return err

  }

  *i=[]Instance{s}

  return nil

}

这会将对象解封为 1 的切片。


@mkopriva提供了更紧凑的解决方案:


func (i *Instances) UnmarshalJSON(in []byte) error {

    if len(in) > 0 && in[0] == '[' {

        return json.Unmarshal(in, (*[]Instance)(i))

    }


    *i = Instances{{}}

    return json.Unmarshal(in, &(*i)[0])

}


查看完整回答
反对 回复 2022-09-19
  • 2 回答
  • 0 关注
  • 62 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信