duansha8764 2015-10-21 09:40
浏览 70
已采纳

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

i'm trying to decode 2 JSON items into the same struct, because the second JSON complet the first one, but it doesn't work (do nothing) have you got some ideas ?

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
}

and the struct

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`
}

The JSON I receive is:

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

The Redis complet the azure search missing information :

here the struct :

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`
}

this is the basic information and redis complet this

I don't want to merge 2 struct into a third one i think it's not the better process, i will do it if it's the last solution.

  • 写回答

2条回答 默认 最新

  • dongqiuge5435 2015-10-22 10:33
    关注

    After a lot of trial and error, I present to you this fully functional solution:

    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
    ",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
    }
    

    What are we doing in the parseJson function?

    We create a new struct and assign that to the toParseInto variable. We design the struct in a way that it contains all of the fields from InfoClip via embedding, and We add a field to temporarily hold the JSON string metas.

    We then unmarshal into that struct, which, after fixing the issues listed below, works fine.

    After that, we unmarshal that inner JSON into the correct field in the embedded InfoClip.

    We can now easily return that embedded InfoClip to get what we really wanted.

    Now, all the issues I have identified in your original solution:

    1. The time format in your JSON is not the standard time format to be used in JSON. That is defined in some RFC, but anyways: because of that, we have to use our own type customTime to parse that. It handles just like a normal time.Time, because that is embedded within.
    2. All your json tags were wrong. All of them had missing quotes, and some were just not even correct.
    3. startTimeCode and endTimeCode are strings in the JSON, not ints

    Left to you to improve:

    • Error handling: Don't just panic in the parseJson function, but rather return the error somehow
    • If you want startTimecode and endTimecode to be available as ints, parse them manually. You can employ a "hack" similar to the one I used to parse the inner JSON.

    One final note, not related to this answer but rather to your question: If you had provided both your code and the JSON with your original question, you would have had an answer in probably less than an hour. Please, please don't make this harder than it needs to be.

    EDIT: I forgot to provide my sources, I used this question to parse your time format.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 R语言卸载之后无法重装,显示电脑存在下载某些较大二进制文件行为,怎么办
  • ¥15 java 的protected权限 ,问题在注释里