【问题标题】:basic json > struct question ( using 'Go')基本 json > 结构问题(使用“Go”)
【发布时间】:2011-01-25 02:26:00
【问题描述】:

我正在使用 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”给了我一些奇怪的东西...

【问题讨论】:

    标签: regex json data-structures map go


    【解决方案1】:

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

    很容易扫描 Twitter JSON 表单中的 "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
    }
    

    注意:结构和字段标识符的第一个字符是大写的,以便可以导出。

    我已经对这种方法进行了编程和测试,它似乎有效。因为这是你的学校项目,所以我还没有发布我的代码。

    【讨论】:

    • 谢谢彼得。 FWIW 我没有对任何代码评分,实际上我没有编写任何代码,只是想展示该语言的功能。这是我真正喜欢上的“编程语言理论”课程。我们现在正在覆盖铁轨......
    【解决方案2】:

    呃,这似乎是 Go 无法解析的 JSON。 Twitter 一直在他们的 API 中提取这种奇怪的东西。

    “趋势”对象是从日期对象到趋势主题数组的映射。不幸的是,Go JSON 解析器不够聪明,无法处理这个问题。

    与此同时,您可以手动解析这种格式,或者只是对主题进行正则表达式搜索。

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

    【讨论】:

    • 没想到手动解析,暂时就这样吧……但是我的结构体看起来是对的吗?
    • 我不确定解析它会出现什么问题。日期被序列化为字符串,这不会导致任何问题。它只是映射到一个字符串而不是一个日期对象。
    • 但是名称(json 中冒号左侧的变量)是否必须在我要解组的结构中具有匹配的变量名称?即:如果“\”2010-03-08 17:23:56“\”是一个“名称”,我如何创建一个变量来保存它?
    • @danwoods,我没有意识到您使用的是Unmarshal,但我想这是有道理的,所以是的,它们确实需要匹配。不过我猜你现在已经想通了。
    【解决方案3】:

    修改为较早的答案。

    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}
    

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

    要将Twitter current trends中的JSON数据读入Go数据结构,使用json包,我们可以做类似下面的事情。

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

    【讨论】:

      猜你喜欢
      • 2019-12-04
      • 2020-08-25
      • 1970-01-01
      • 2019-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多