基本的json> struct问题(使用'Go')

时间:2010-03-08 18:06:02

标签: regex json data-structures map go

我正在使用twitter的api,尝试从

获取json数据
http://search.twitter.com/trends/current.json

看起来像:

{"as_of":1268069036,"trends":{"2010-03-08 17:23:56":[{"name":"Happy Women's Day","query":"\"Happy Women's Day\" OR \"Women's Day\""},{"name":"#MusicMonday","query":"#MusicMonday"},{"name":"#MM","query":"#MM"},{"name":"Oscars","query":"Oscars OR #oscars"},{"name":"#nooffense","query":"#nooffense"},{"name":"Hurt Locker","query":"\"Hurt Locker\""},{"name":"Justin Bieber","query":"\"Justin Bieber\""},{"name":"Cmon","query":"Cmon"},{"name":"My World 2","query":"\"My World 2\""},{"name":"Sandra Bullock","query":"\"Sandra Bullock\""}]}}

我的结构如下:

type trend struct {  
 name  string  
 query string  
}  

type trends struct {  
 id string  
 arr_of_trends []trend  
}  

type Trending struct {  
 as_of  string  
 trends_obj trends  
}

然后我将JSON解析为Trending类型的变量。我是JSON的新手,所以我主要关心的是确保我已正确设置数据结构来保存返回的json数据。

我正在“Go”中为学校的项目写这篇文章。 (这不是特定任务的一部分,只是我正在演示的语言演示文稿)

更新:根据PeterSO的评论,我正在进行正则表达式路线。使用:

Cur_Trends := new(Current)
/* unmarshal the JSON into our structures */

//find proper json time-name
aoUnixTime, _, _ := os.Time()

// insert code to find and convert as_of Unix time to aoUnixTime
    aoName := time.SecondsToUTC(aoUnixTime).Format(`"2006-01-02"`)
    fmt.Printf("%s\n", aoName)
    regexp_pattern := "/" + aoName + "/"
    regex, _ := regexp.Compile(regexp_pattern);

    cleaned_json := regex.ReplaceAllString(string(body2), "ntrends")
    os.Stdout.WriteString(cleaned_json)

不显示任何更改。我指的是正则表达式错误吗?似乎'Go'一次只能允许一个正则表达式...

更新: 现在可以将日期/时间更改为“ntrends”,但“Unmarshaling”不起作用。我可以使用json.Decode将所有内容移动到接口中,但不能遍历它...

我想我的新问题是,如何迭代:

map[as_of:1.268176902e+09 trends:map[ntrends:[map[name:#nowplaying query:#nowplaying] map[name:#imtiredofseeing query:#imtiredofseeing] map[name:#iWillNever query:#iWillNever] map[name:#inmyfamily query:#inmyfamily] map[name:#raiseyourhandif query:#raiseyourhandif] map[name:#ripbig query:#ripbig] map[name:QVC query:QVC] map[name:#nooffense query:#nooffense] map[name:#RIPLaylaGrace query:#RIPLaylaGrace] map[name:Justin Bieber query:"Justin Bieber"]]]]

使用“for ... range”给了我奇怪的东西......

3 个答案:

答案 0 :(得分:2)

Twitter因其Fail Whale而闻名,Twitter API也因此失败;太可怕了。

Twitter trends current Search API method响应可以在规范的,规范化的JSON格式中表达(仅使用两种趋势来简化示例):

{
    "as_of":1268069036,
    "trends":[
        {"name":"Happy Women's Day","query":"\"Happy Women's Day\" OR \"Women's Day\""},
        {"name":"#MusicMonday","query":"#MusicMonday"},{"name":"#MM","query":"#MM"}
    ]
}

as_of日期是Unix时间,即自1970年1月1日以来的秒数。

在Go中,这可以通过以下方式描述:

type Trend struct {
    Name  string
    Query string
}

type Current struct {
    As_of  int64
    Trends []Trend
}

Twitter将规范的规范化JSON格式破坏成:

{
    "as_of":1268069036,
    "trends":{
        "2010-03-08 17:23:56":[
            {"name":"Happy Women's Day","query":"\"Happy Women's Day\" OR \"Women's Day\""},
            {"name":"#MusicMonday","query":"#MusicMonday"}
        ]
    }
}

有时,Twitter会返回此等效的JSON表单。

{
    "trends":{
        "2010-03-08 17:23:56":[
            {"name":"Happy Women's Day","query":"\"Happy Women's Day\" OR \"Women's Day\""},
            {"name":"#MusicMonday","query":"#MusicMonday"}
        ]
    },
    "as_of":1268069036
}

"2010-03-08 17:23:56":是一个JSON对象名。但是,它是 - 无意义的 - 字符串形式的as_of

如果我们用对象名"2010-03-08 17:23:56":替换"ntrends":(对于嵌套趋势),覆盖多余的as_of字符串时间,我们会修改以下Twitter JSON表单:

{
    "as_of":1268069036,
    "trends":{
        "ntrends":[
            {"name":"Happy Women's Day","query":"\"Happy Women's Day\" OR \"Women's Day\""},
            {"name":"#MusicMonday","query":"#MusicMonday"}
        ]
    }
}

很容易扫描{J}表格"as_of":,读取以下数字作为as_of Unix时间,并将其转换为JSON名称形式,例如:

var aoUnixTime int64
// insert code to find and convert as_of Unix time to aoUnixTime
aoName := time.SecondsToUTC(aoUnix).Format(`"2006-01-02 15:04:05":`)

现在我们可以扫描Twitter JSON表单中的aoName值,并将其替换为"ntrends":以获取修订后的Twitter JSON表单。

在Go中,修订后的Twitter JSON表单可以通过以下方式描述:

type Trend struct {
    Name  string
    Query string
}

type NTrends struct {
    NTrends []Trend
}

type Current struct {
    As_of  int64
    Trends NTrends
}

注意:struct和field标识符的第一个字符是大写的,以便可以导出它们。

我编程并测试了这种方法,它似乎有效。由于这是一个适合您的学校项目,我还没有发布我的代码。

答案 1 :(得分:1)

呃,这看起来像Go无法解析的JSON。 Twitter在他们的API中始终提取这种奇怪的东西。

'trends'对象是从日期对象到趋势主题数组的映射。不幸的是,Go JSON解析器不够智能来处理这个问题。

在此期间,您可以手动解析此格式,或者只是对主题进行正则表达式搜索。

无论哪种方式,我都会将此作为Go问题发布,看看他们说了什么: http://code.google.com/p/go/issues/list

答案 2 :(得分:1)

修订早期答案。

Twitter搜索API方法趋势响应采用方便的规范和规范化JSON格式:

{"trends":[{"name":"#amazonfail","url":"http:\/\/search.twitter.com\/search?q=%23amazonfail"},... truncated ...],"as_of":"Mon, 13 Apr 2009 20:48:29 +0000"}

Twitter搜索API方法趋势当前,每日和每周回复是一个不必要的JSON形式,类似于:

{"trends":{"2009-03-19 21:00":[{"query":"AIG","name":"AIG"},... truncated ...],... truncated ...},"as_of":1239656409}

明显违反了算法和数据结构封装的规则,这不必要地披露了目前这些方法使用地图或字典来实现它们。

要使用json包将Twitter current trends中的JSON数据读入Go数据结构,我们可以执行类似以下的操作。

package main

import (
    "fmt"
    "json"
)

type Trend struct {
    Name  string
    Query string
}

type Current struct {
    As_of  int64
    Trends map[string][]Trend
}

var currentTrends = `{"as_of":1268069036,"trends":{"2010-03-08 17:23:56":[{"name":"Happy Women's Day","query":"\"Happy Women's Day\" OR \"Women's Day\""},{"name":"#MusicMonday","query":"#MusicMonday"},{"name":"#MM","query":"#MM"},{"name":"Oscars","query":"Oscars OR #oscars"},{"name":"#nooffense","query":"#nooffense"},{"name":"Hurt Locker","query":"\"Hurt Locker\""},{"name":"Justin Bieber","query":"\"Justin Bieber\""},{"name":"Cmon","query":"Cmon"},{"name":"My World 2","query":"\"My World 2\""},{"name":"Sandra Bullock","query":"\"Sandra Bullock\""}]}}`

func main() {
    var ctJson = currentTrends
    var ctVal = Current{}
    ok, errtok := json.Unmarshal(ctJson, &ctVal)
    if !ok {
        fmt.Println("Unmarshal errtok: ", errtok)
    }
    fmt.Println(ctVal)
}