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

Golang 将 2 个 JSON 项解码为 1 个结构体

Golang 将 2 个 JSON 项解码为 1 个结构体

Go
GCT1015 2021-11-15 20:41:56
我正在尝试将 2 个 JSON 项目解码为同一个结构,因为第二个 JSON 完成了第一个,但它不起作用(什么都不做)你有什么想法吗?func getUserClip(this *LibraryController, id string) (*Clip){//Test Api//Send Request to azure searchData := Clip{}if req := GetClipById("b373400a-bd7e-452a-af68-36992b0323a5"); req == nil {    return nil} else {    str, err := req.String()    if err != nil {        beego.Debug("Error Json req.String: ", err)    }    //Uncode Json to string    if err := json.Unmarshal([]byte(str), &Data); err != nil {        beego.Debug("Error json", err)    }    for i := range Data.Value {        if req = GetCliRedis(Data.Value[i].Id); err != nil {            return nil        } else {            str, err := req.String()            beego.Debug("JSON REDIS DEBUG: ", str)            if err != nil {                beego.Debug("Error Json req.String: ", err)            }            if err := json.Unmarshal([]byte(str), &Data); err != nil {                beego.Debug("Error json", err)            }        }        i++    }   }  return &Data}和结构type Clip struct {Value   []InfoClip `json:value`}type InfoClip struct {Id                  string      `json:id`CreatedAt           time.Time   `json:createdAt`StartTimeCode       int         `json:startTimeCode`EndTimeCode         int         `json:endTimeCode`Metas               metas       `json:metas`Tags                []string    `json:tags`Categories          []string    `json:categories`UserId              string      `json:userId`SourceId            string      `json:sourceId`ProviderName        string      `json:providerName`ProviderReference   string      `json:providerReference`PublicationStatus   string      `json:publicationStatus`Name                string      `json:name`FacebookPage        string      `json:facebookPage`TwitterHandle       string      `json:twitterHandle`PermaLinkUrl        string      `json:permalinkUrl`Logo                string      `json:logo`Link                string      `json:link`Views               int         `json:views`}
查看完整描述

2 回答

?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

由于缺乏活动,我将发布嵌入选项作为解决方案。这可能是做你想做的最简单的方法。


type ClipInfoAndMeta struct {

      Metas

      InfoClip

}

请注意,我metas不确定是否需要将名称大写,但我相信它会是。此处使用的语言功能称为“嵌入”,它的工作方式与组合非常相似,只是嵌入类型的字段/方法或多或少会“提升”到包含类型的范围。带有实例的 IEClipInfoAndMeta可以直接访问定义在 上的任何导出字段InfoClip。


您设置的一个奇怪之处是您将在两种类型之间的字段名称上发生冲突。不知道会如何发展。说了这么多,查看您试图从中解组的 json 字符串会很有帮助。在我写这篇文章时,我意识到这metas只是InfoClip. 这让我对你实际上想要做什么感到困惑?我的意思是,如果返回的数据全部在一个对象中,则意味着InfoClip足以存储所有数据。如果是这种情况,你就没有理由使用另一个对象......如果你想修剪传递给你的应用程序显示层的字段,你应该只在InfoClip类型上定义一个方法,func (i *InfoClip) GetMetas() Metas { return &Metas{ ... } }然后你就可以处理了到处都是一种类型,然后交出Metas 需要时到显示层。


查看完整回答
反对 回复 2021-11-15
?
守着星空守着你

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

经过大量的反复试验,我向您展示了这个功能齐全的解决方案:


package main


import (

    "encoding/json"

    "fmt"

    "log"

    "time"

)


type Clip struct {

    Value []InfoClip `json:value`

}


type customTime struct {

    time.Time

}


const ctLayout = "2006-01-02 15:04:05"


func (ct *customTime) UnmarshalJSON(b []byte) (err error) {

    if b[0] == '"' && b[len(b)-1] == '"' {

        b = b[1 : len(b)-1]

    }

    ct.Time, err = time.Parse(ctLayout, string(b))

    return

}


type InfoClip struct {

    Id                string     `json:"clipId"`

    CreatedAt         customTime `json:"createdAt"`

    StartTimeCode     string     `json:"startTimeCode"` //if you want ints here, you'll have to decode manually, or fix the json beforehand

    EndTimeCode       string     `json:"endTimeCode"`   //same for this one

    Metas             metas      `json:"-"`

    MetasString       string     `json:"metas"`

    Tags              []string   `json:"tags"`

    Categories        []string   `json:"categories"`

    UserId            string     `json:"userId"`

    SourceId          string     `json:"sourceId"`

    ProviderName      string     `json:"providerName"`

    ProviderReference string     `json:"providerReference"`

    PublicationStatus string     `json:"publicationStatus"`

    Name              string     `json:"name"`

    FacebookPage      string     `json:"facebookPage"`

    TwitterHandle     string     `json:"twitterHandle"`

    PermaLinkUrl      string     `json:"permalinkBaseURL"`

    Logo              string     `json:"logo"`

    Link              string     `json:"link"`

    Views             int        `json:"views"`

}


type metas struct {

    Title      string   `json:"title"`

    Tags       []string `json:"tags"`

    Categories []string `json:"categories"`

    PermaLink  string   `json:"permalink"`

}


var jsonString = `{  

   "clipId":"9b2ea9bb-e54b-4291-ba16-9211fa3c755f",

   "streamUrl":"https://<edited out>/asset-32e43a5d-1500-80c3-cc6b-f1e4fe2b5c44\/6c53fbf5-dbe9-4617-9692-78e8d76a7b6e_H264_500kbps_AAC_und_ch2_128kbps.mp4?sv=2012-02-12&sr=c&si=17ed71e8-5176-4432-8092-ee64928a55f6&sig=KHyToRlqvwQxWZXVvRYOkBOBOF0SuBLVmKiGp4joBpw%3D&st=2015-05-18T13%3A32%3A41Z&se=2057-05-07T13%3A32%3A41Z",

   "startTimecode":"6",

   "endTimecode":"16",

   "createdAt":"2015-05-19 13:31:32",

   "metas":"{\"title\":\"Zapping : Obama, Marine Le Pen et Michael Jackson\",\"tags\":[\"actualite\"],\"categories\":[\"actualite\"],\"permalink\":\"http:\/\/videos.lexpress.fr\/actualite\/zapping-obama-marine-le-pen-et-michael-jackson_910357.html\"}",

   "sourceId":"6c53fbf5-dbe9-4617-9692-78e8d76a7b6e",

   "providerName":"dailymotion",

   "providerReference":"x1xmnxq",

   "publicationStatus":"1",

   "userId":"b373400a-bd7e-452a-af68-36992b0323a5",

   "name":"LEXPRESS.fr",

   "facebookPage":"https:\/\/www.facebook.com\/LExpress",

   "twitterHandle":"https:\/\/twitter.com\/lexpress",

   "permalinkBaseURL":"https:\/\/tym.net\/fr\/{CLIP_ID}",

   "logo":"lexpress-120px.png",

   "link":"http:\/\/videos.lexpress.fr\/"

}`


func main() {

    res := parseJson(jsonString)

    fmt.Printf("%+v\n",res)

}


func parseJson(theJson string) InfoClip {

    toParseInto := struct {

        InfoClip

        MetasString string `json:"metas"`

    }{

        InfoClip:    InfoClip{},

        MetasString: ""}


    err := json.Unmarshal([]byte(jsonString), &toParseInto)

    if err != nil {

        log.Panic(err)

    }


    err = json.Unmarshal([]byte(toParseInto.MetasString), &toParseInto.InfoClip.Metas)

    if err != nil {

        log.Panic(err)

    }


    return toParseInto.InfoClip

}

我们在parseJson函数中做什么?


我们创建一个新结构并将其分配给toParseInto变量。我们设计结构的方式是它包含来自InfoClipvia embedding 的所有字段,并且我们添加一个字段来临时保存 JSON 字符串metas。


然后我们解组到该结构中,在解决下面列出的问题后,它可以正常工作。


之后,我们将该内部JSON解组到嵌入的.json 文件中的正确字段中InfoClip。


我们现在可以轻松返回嵌入的内容InfoClip以获得我们真正想要的内容。


现在,我在您的原始解决方案中发现的所有问题:

  1. JSON 中的时间格式不是 JSON 中使用的标准时间格式。这是在某些 RFC 中定义的,但无论如何:因此,我们必须使用我们自己的类型customTime来解析它。它的处理就像一个普通的time.Time,因为它嵌入在里面。

  2. 所有的 json 标签都是错误的。他们都缺少引号,有些甚至不正确。

  3. startTimeCode并且endTimeCode是 JSON 中的字符串,而不是整数

留给你改进:

  • 错误处理:不要只是在parseJson函数中恐慌,而是以某种方式返回错误

  • 如果您希望startTimecodeendTimecode作为整数可用,请手动解析它们。您可以使用类似于我用来解析内部 JSON 的“hack”。

最后一个说明,与此答案无关,而是与您的问题相关:如果您提供了原始问题的代码和 JSON,那么您可能会在不到一个小时的时间内得到答案。不要让这变得比需要的更难。

编辑:我忘了提供我的来源,我用这个问题来解析你的时间格式。


查看完整回答
反对 回复 2021-11-15
  • 2 回答
  • 0 关注
  • 263 浏览
慕课专栏
更多

添加回答

举报

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