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

如何定义具有不同字段类型的 GoLang 结构

如何定义具有不同字段类型的 GoLang 结构

Go
慕虎7371278 2022-08-24 17:02:58
我对GoLang比较陌生,并且在严格的类型系统中遇到了麻烦(我更习惯于弱类型语言)。在尝试编写Alexa智能家居技能时,我需要创建定义(例如)的JSON结构 https://developer.amazon.com/en-US/docs/alexa/device-apis/alexa-contactsensor.html国家报告回应是我开始遇到麻烦的地方,特别是在上下文中。该示例如下所示:  "context": {    "properties": [      {        "namespace": "Alexa.ContactSensor",        "name": "detectionState",        "value": "NOT_DETECTED",        "timeOfSample": "2017-02-03T16:20:50.52Z",        "uncertaintyInMilliseconds": 0      },      {        "namespace": "Alexa.EndpointHealth",        "name": "connectivity",        "value": {          "value": "OK"        },        "timeOfSample": "2017-02-03T16:20:50.52Z",        "uncertaintyInMilliseconds": 0      }    ]  }乍一看,这看起来很简单:    Context struct {        Properties []struct {            Namespace                 string    `json:"namespace"`            Name                      string    `json:"name"`            Value                     string    `json:"value"`            Timeofsample              time.Time `json:"timeOfSample"`            Uncertaintyinmilliseconds int       `json:"uncertaintyInMilliseconds"`        } `json:"properties"`    } `json:"context"`但是“值”字段是我遇到问题的地方。在数组的第一个元素中,我们有一个简单的字符串        "value": "NOT_DETECTED",但第二个元素是一个结构        "value": {          "value": "OK"        },(这似乎不是文档中的拼写错误;它在 https://developer.amazon.com/en-US/docs/alexa/device-apis/alexa-endpointhealth.html 和其他地方也重复出现)。这就是GoLang的严格输入和我对语言的了解开始击败我的地方。如何对此元素进行建模,因为它似乎没有固定类型?value还是有更好的方法来做到这一点?
查看完整描述

2 回答

?
梦里花落0921

TA贡献1772条经验 获得超6个赞

创建一个类似如下的类型:


import (

    "bytes"

    "encoding/json"

    "fmt"

)


// nullOK is a JSON OK literal

var nullOK = []byte("OK")


type ValueString struct {

    Error string

    Valid bool

}


// UnmarshalJSON implements json.Unmarshaler.

func (s *ValueString) UnmarshalJSON(data []byte) error {

    if bytes.Equal(data, nullOK) {

        s.Valid = true

        return nil

    }


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

        return fmt.Errorf("checking OK: couldn't unmarshal JSON: %w", err)

    }


    s.Valid = false

    return nil

}


// MarshalJSON implements json.Marshaler.

func (s ValueString) MarshalJSON() ([]byte, error) {

    if s.Valid {

        return []byte("OK"), nil

    }

    return json.Marshal(s.Error)

}

并在您的结构中使用它:


...

Value                     ValueString    `json:"value"`

...

当值为“OK”时,您的将是 ,否则请检查解析值。Value.ValidtrueValue.Error


查看完整回答
反对 回复 2022-08-24
?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

使用mkopriva的提示,我想我提出了使用和匿名结构的简单概念验证解决方案interface{}


package main


import "encoding/json"

import "fmt"


type Foo struct {

        Value interface{} `json:"value"`

}


func main() {

        v1 := Foo{Value: "version1"}

        j1, _ := json.Marshal(v1)

        fmt.Println(string(j1))


        v2 := Foo{Value: struct {

                Value string `json:"value"`

        }{Value: "version2"}}

        j2, _ := json.Marshal(v2)

        fmt.Println(string(j2))

}

运行此命令会得到两个输出:


{"value":"version1"}

{"value":{"value":"version2"}}


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

添加回答

举报

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