базовый вопрос о json> struct (с использованием 'Go') - PullRequest
5 голосов
/ 08 марта 2010

Я работаю с 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» допускает только одно регулярное выражение за раз ...

UPDATE: Теперь можно изменить дату / время на «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 ]

2 голосов
/ 09 марта 2010

Twitter известен своим Fail Whale , а Twitter API также получает неудовлетворительную оценку; это ужасно.

Твиттер тренды текущий метод API поиска ответ может быть выражен (используя только две тенденции для упрощения примеров) в канонической нормализованной форме 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-времени, в секундах с 1/1970 / *.

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

Легко отсканировать форму JSON в Twitter на "as_of":, прочитать следующее число как as_of время Unix и преобразовать его в форму имени JSON, например ::101036

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 исправленная форма JSON в Twitter может быть описана следующим образом:

type Trend struct {
    Name  string
    Query string
}

type NTrends struct {
    NTrends []Trend
}

type Current struct {
    As_of  int64
    Trends NTrends
}

Примечание: первый символ идентификаторов структуры и поля в верхнем регистре, чтобы их можно было экспортировать.

Я запрограммировал и протестировал этот подход, и, похоже, он работает. Поскольку это школьный проект для вас, я не опубликовал свой код.

1 голос
/ 10 марта 2010

Редакция к предыдущему ответу.

Ответ о тенденциях метода API поиска в Твиттере находится в удобной канонической и нормализованной форме JSON:

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

Методы API поиска в Твиттере отображают текущие, ежедневные и еженедельные ответы в ненужной неудобной форме JSON, похожей на:

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

В явном нарушении правил инкапсуляции алгоритмов и структур данных это излишне раскрывает, что в настоящее время эти методы используют карту или словарь для их реализации.

Чтобы прочитать данные JSON из текущих тенденций Twitter в структуры данных 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)
}
1 голос
/ 09 марта 2010

Тьфу, это похоже на JSON, который Go не может разобрать. Твиттер постоянно тянет такие странные вещи в своем API.

Объект «тренды» - это карта от объектов дат до массива актуальных тем. К сожалению, анализатор Go JSON недостаточно умен, чтобы справиться с этим.

Тем временем вы можете вручную проанализировать этот формат или просто выполнить поиск по темам с помощью регулярных выражений.

В любом случае, я бы опубликовал это как выпуск Go и посмотрел, что они говорят: http://code.google.com/p/go/issues/list

...