2

I'm trying to get informations from my db, and one of my fields is actually JSON stored as a string and I would like to get it as a struct.

This is my row's struct :

//there is json flag because I use it to get data from redis too
type InfoClip struct {
 ClipId             string `json:clipId`
 StreamUrl          string `json:streamUrl`
 StartTimeCode      int `json:startTimeCode`
 EndTimeCode        int `json:endTimeCode`
 CreatedAt          string `json:createdAt`
 Metas              string `json:metas` // here I get a string instead of a 'metas' struct
 SourceId           string `json:sourceId`
 ProviderName       string `json:providerName`
 ProviderReference  string `json:providerReference`
 PublicationStatus  string `json:publicationStatus`
 UserId             string `json:userId`
 Name               string `json:name`
 FacebookPage       string `json:facebookPage`
 TwitterHandle      string `json:twitterHandle`
 PermaLinkUrl       string `json:permalinkUrl`
 Logo               string `json:logo`
 Link               string `json:link`
}

This is my metas struct :

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

This is how I'm trying to get this field

func decodeJsonSql (met string) (*metas, error) {
 m := metas{}
 if err := json.Unmarshal([]byte(met), &m); err != nil {
    fmt.Printf("Error decode metas: ", err)
    return nil, err
 } else {
    return &m, err
 }
 } 

func CheckIdSql(mediaId string) (error){
 datab, err := sql.Open("mysql", "tcp()")
 if err != nil {
    fmt.Printf("[SQL ERROR] Cannot Open db => ", err)
    return err
}
if err := datab.Ping(); err != nil {
    fmt.Printf("[SQL ERROR] db connection => ", err)
    return err
}
fmt.Printf("[SQL ONLINE] =>", datab)
defer datab.Close()

q := "SELECT c.id AS clipId, c.streamUrl, c.startTimecode,  c.endTimecode, c.createdAt, s.metas,... FROM clips WHERE c.id = ?"
rows, err := datab.Query(q, mediaId)
if err != nil || err == sql.ErrNoRows {
    fmt.Printf("SQL Err: %s", err)
    return err
}
clips := InfoClip{}
for rows.Next() {
    rows.Scan(&clips.ClipId, &clips.StreamUrl, &clips.StartTimeCode, &clips.EndTimeCode, &clips.CreatedAt, &clips.Metas, ...)
}
ret, err := decodeJsonSql(clips.Metas)
if err != nil{
    return err
}
clips.Metas = ret
fmt.Printf("\n\n[SQL DEBUG RESPONSE]: %v", clips)
return nil
}

But this process is pretty heavy, surely there is an easier way? Thanks.

1
  • 2
    I don't understand what your question is, could you please state it more clearly? Commented Oct 16, 2015 at 17:38

1 Answer 1

14

You can make your metas struct implement the sql.Scanner interface

It should look something like this:

func (m *metas) Scan(src interface{}) error {
    strValue, ok := src.(string)

    if !ok {
        return fmt.Errorf("metas field must be a string, got %T instead", src)
    }

    return json.Unmarshal([]byte(strValue), m)
}

After that you can use it as an InfoClip field and pass it directly to Scan and drop the decodeJsonSql:

type InfoClip struct {
    // [...]
    Metas metas `json:metas`
    // [...]
}

and

q := "SELECT c.id AS clipId, c.streamUrl, c.startTimecode,  c.endTimecode, c.createdAt, s.metas,... FROM clips WHERE c.id = ?"
row := datab.QueryRow(q, mediaId)
clips := InfoClip{}
err := row.Scan(&clips.ClipId, &clips.StreamUrl, &clips.StartTimeCode, &clips.EndTimeCode, &clips.CreatedAt, &clips.Metas) // [...]
if err != nil {
    fmt.Printf("SQL Err: %s", err)
    return err
}

(BTW, as you can see, I replaced datab.Query with datab.QueryRow as you are expecting only one result)

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the correction ;) i will test it tonight
I don't understand how to implement it, how can i get the metas values with this interface in the "row.Next" ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.