基本的 JSON 转结构体问题(使用 ‘Go’)

huangapple go评论110阅读模式
英文:

basic json > struct question ( using 'Go')

问题

我正在使用Twitter的API,尝试从http://search.twitter.com/trends/current.json获取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)
/* 将JSON解析为我们的结构体 */

//找到正确的JSON时间名称
aoUnixTime, _, _ := os.Time()

//插入代码来找到并将as_of Unix时间转换为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”给我奇怪的结果...

英文:

I'm working with twitter's api, trying to get the json data from

http://search.twitter.com/trends/current.json

which looks like:

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

My structs look like:

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  
}

and then I parse the JSON into a variable of type Trending. I'm very new to JSON so my main concern is making sure I've have the data structure correctly setup to hold the returned json data.

I'm writing this in 'Go' for a project for school. (This is not part of a particular assignment, just something I'm demo-ing for a presentation on the language)

UPDATE: In accordance with PeterSO's comment I'm going the regexp route. Using:

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)

Doesn't show any changes. Am I specifying the regexp wrong? It seems like 'Go' only allows for one regexp at a time...

UPDATE:
can now change the date/time to "ntrends" but the "Unmarshaling" isn't working. I can get everything moved into an interface using json.Decode, but can't iterate through it...

I guess my new question is, How do I iterate through:

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

using "for...range" is giving me weird stuff...

答案1

得分: 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的字符串形式,这是没有意义的。

如果我们用对象名称"ntrends":(表示嵌套趋势)替换"2010-03-08 17:23:56":,覆盖多余的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
// 插入代码以查找并将as_of Unix时间转换为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
}

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

我已经编写并测试了这种方法,似乎可以工作。由于这是你的学校项目,我没有发布我的代码。

英文:

Twitter is famous for its Fail Whale, and the Twitter API gets a failing grade too; it's horrible.

Twitter trends current Search API method response can be expressed (using just two trends to simplify the examples) in canonical, normalized JSON form as:

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

The as_of date is in Unix time, the number of seconds since 1/1/1970.

In Go, this can be described by:

type Trend struct {
    Name  string
    Query string
}

type Current struct {
    As_of  int64
    Trends []Trend
}

Twitter mangles the canonical, normalized JSON form to become:

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

Sometimes, Twitter returns this equivalent JSON form.

{
	"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": is a JSON object name. However, it's -- nonsensically -- a string form of as_of.

If we replace "2010-03-08 17:23:56": by the object name "ntrends": (for nested trends), overwriting the redundant as_of string time, we have the following revised Twitter JSON form:

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

It's easy to scan the Twitter JSON form for "as_of":, read the following number as the as_of Unix time, and convert it to JSON name form e.g.:

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":`)

Now we can scan the Twitter JSON form for the aoName value and replace it with "ntrends": to get the revised Twitter JSON form.

In Go, the revised Twitter JSON form can be described by:

type Trend struct {
    Name  string
    Query string
}

type NTrends struct {
    NTrends []Trend
}

type Current struct {
    As_of  int64
    Trends NTrends
}

Note: the first character of the struct and field identifiers are uppercase so that they can be exported.

I've programmed and tested this approach and it seems to work. Since this is a school project for you, I haven't published my code.

答案2

得分: 1

Ugh,这似乎是Go无法解析的JSON。Twitter API中经常出现这种奇怪的东西。

'trends'对象是一个从日期对象到一个流行话题数组的映射。不幸的是,Go的JSON解析器不够智能,无法处理这种情况。

在此期间,您可以手动解析这种格式,或者只是使用正则表达式搜索话题。

无论哪种方式,我建议您将此问题发布为Go的问题,并看看他们的回答:
http://code.google.com/p/go/issues/list

英文:

Ugh, this seems like JSON that Go can't parse. Twitter pulls this kind of weird stuff all the time in their API.

The 'trends' object is a map from date objects to an array of trending topics. Unfortunately the Go JSON parser isn't smart enough to handle this.

In the meantime you could manually parse this format, or just do a regular expression search for the topics.

Either way, I'd post this as a Go issue and see what they say:
http://code.google.com/p/go/issues/list

答案3

得分: 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}

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

为了将Twitter当前趋势的JSON数据读入Go数据结构中,可以使用json包,类似于以下操作。

package main

import (
	"fmt"
	"encoding/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([]byte(ctJson), &ctVal)
	if !ok {
		fmt.Println("Unmarshal errtok: ", errtok)
	}
	fmt.Println(ctVal)
}
英文:

Revision to earlier answer.

The Twitter Search API Method trends response is in convenient canonical and normalized JSON form:

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

The Twitter Search API Methods trends current, daily and weekly responses are, however, in an unnecessarily inconvenient JSON form similar to:

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

In clear violation of the rules for the encapsulation of algorithms and data structures, this unnecessarily discloses that currently these methods use a map or dictionary for their implementation.

To read the JSON data from Twitter current trends into Go data structures, using the json package, we can do something similar to the following.

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

huangapple
  • 本文由 发表于 2010年3月9日 02:06:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/2403520.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定