我正在尝试从数据库中获取信息,而我的字段之一实际上是将JSON存储为字符串,并且希望将其作为结构体获取。
这是我行的结构:
//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`
}
Run Code Online (Sandbox Code Playgroud)
这是我的metas结构:
type metas struct {
Title string `json:title`
Tags []string `json:tags`
categories []string `json:permalink`
}
Run Code Online (Sandbox Code Playgroud)
这就是我试图获取此字段的方式
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
}
Run Code Online (Sandbox Code Playgroud)
但是这个过程很繁琐,肯定有更简单的方法吗?谢谢。
您可以使您的metas结构实现sql.Scanner接口
它看起来应该像这样:
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)
}
Run Code Online (Sandbox Code Playgroud)
之后,您可以将其用作InfoClip字段并将其直接传递到Scan并放置decodeJsonSql:
type InfoClip struct {
// [...]
Metas metas `json:metas`
// [...]
}
Run Code Online (Sandbox Code Playgroud)
和
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
}
Run Code Online (Sandbox Code Playgroud)
(顺便说一句,你可以看到,我换成datab.Query与datab.QueryRow你期待只有一个结果)