簡體   English   中英

Golang將2個JSON項目解碼為1個結構

[英]Golang decode 2 JSON items into 1 struct

我正在嘗試將2個JSON項目解碼為相同的結構,因為第二個JSON完成了第一個JSON,但是它不起作用(什么也不做),您有什么主意嗎?

func getUserClip(this *LibraryController, id string) (*Clip){
//Test Api
//Send Request to azure search
Data := 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`
}

type metas struct {
Title               string      `json:title`
Tags                []string    `json:tags`
Categories          []string    `json:categories`
PermaLink           string      `json:permalink`
}

我收到的JSON是:

{  
   "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\/"
}

Redis完成了天藍色搜索缺少的信息:

這里的結構:

type Clip struct {
Value   []SearchClip `json:value`
}

type SearchClip struct {
Id                  string `json:id`
CreatedAt           string`json:createdAt`
Tags                []string `json:tags`
Categories          []string `json:categories`
UserId              string `json:userId`
SourceId            string `json:sourceId`
Views               int `json:views`
}

這是基本信息,請重新完成

我不想將2個結構合並到第三個結構中,我認為這不是更好的過程,如果這是最后的解決方案,我會做的。

由於缺乏活動性,我將發布嵌入選項作為解決方案。 這可能是您要做的最簡單的方法。

type ClipInfoAndMeta struct {
      Metas
      InfoClip
}

請注意,我在metas上大寫了該名稱,不確定是否有必要,但我相信會是。 此處使用的語言功能稱為“嵌入”,它的工作原理與合成非常相似,不同之處在於嵌入式類型的字段/方法或多或少地“提升”到了包含類型的范圍。 帶有ClipInfoAndMeta實例的IE,您可以直接訪問在InfoClip上定義的任何導出字段。

設置的一個奇怪之處是,兩種類型之間的字段名稱會發生​​沖突。 不確定如何播放。 綜上所述,查看您要從中解組的json字符串將很有幫助。 在撰寫本文時,我意識到metas只是InfoClip一個子集。 哪個讓我對您實際上要做什么感到困惑? 我的意思是,如果返回的數據全部集中在一個對象中,則意味着InfoClip足以存儲所有數據。 如果是這種情況,那么您就沒有理由使用其他對象...而且,如果您想縮小傳遞給應用程序顯示層的字段,則只需在InfoClip類型上定義一個方法,例如func (i *InfoClip) GetMetas() Metas { return &Metas{ ... } }然后,您可以隨處處理一種類型,並在需要時將Metas傳遞給顯示層。

經過大量的試驗和錯誤,我向您介紹此功能齊全的解決方案:

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變量。 我們通過以下方式設計該結構,使其包含來自InfoClip所有字段(通過嵌入),並添加一個字段以臨時保存JSON字符串metas

然后,我們將解組到該結構中,在解決了以下所列問題之后,該結構可以正常工作。

之后,我們將內部 JSON解組到嵌入式InfoClip的正確字段中。

現在,我們可以輕松返回該嵌入式InfoClip以獲取我們真正想要的東西。

現在,我在原始解決方案中發現的所有問題:

  1. JSON中的時間格式不是JSON中使用的標准時間格式。 那是在一些RFC中定義的,但是無論如何:因此,我們必須使用我們自己的類型customTime來解析它。 它像正常的time.Time一樣處理,因為它嵌入其中。
  2. 所有的json標簽都錯了。 他們全都缺少引號,有些甚至不正確。
  3. startTimeCodeendTimeCode是JSON中的字符串,而不是ints

留給您改進:

  • 錯誤處理:不要只是在parseJson函數中驚慌,而是以某種方式返回錯誤
  • 如果希望startTimecodeendTimecode可以作為整數使用,請手動解析它們。 您可以采用一種類似於我用來解析內部JSON的“ hack”。

最后一點,與該答案無關,而與您的問題有關:如果您在原始問題中同時提供了代碼和JSON,則可能會在不到一個小時的時間內得到答案。 拜托不要讓它變得比需要的難。

編輯:我忘記提供我的資源,我用這個問題來解析您的時間格式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM