базовый вопрос json > struct (используя 'Go')
-
18-09-2019 - |
Вопрос
Я работаю с API Twitter, пытаясь получить данные 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" для проекта для школы.(Это не часть конкретного задания, просто то, что я демонстрирую для презентации по языку)
Обновить:В соответствии с комментарием ПетерСО, я использую маршрут регулярных выражений.Используя:
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", но "Отмена сопоставления" не работает.Я могу перенести все в интерфейс, используя json.Декодирую, но не могу выполнить итерацию по нему...
Я предполагаю, что мой новый вопрос заключается в том, как мне выполнить итерацию через:
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"]]]]
использование "для ... диапазона" дает мне странные результаты...
Решение
Twitter славится своими Потерпев Неудачу , Кит, и в Twitter API тоже получает неудовлетворительную оценку;это ужасно.
Twitter тренды текущий метод поиска 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/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"}
]
}
}
Легко отсканировать форму 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
}
Примечание:первый символ структуры и идентификаторы полей написаны заглавными буквами, чтобы их можно было экспортировать.
Я запрограммировал и протестировал этот подход, и, похоже, он работает.Поскольку это школьный проект для вас, я не публиковал свой код.
Другие советы
Фу, это похоже на JSON, который Go не может разобрать.Twitter постоянно использует подобные странные вещи в своем API.
Объект "тренды" представляет собой сопоставление объектов date с массивом актуальных тем.К сожалению, анализатор Go JSON недостаточно умен, чтобы справиться с этим.
Тем временем вы могли бы вручную проанализировать этот формат или просто выполнить поиск по темам с помощью регулярного выражения.
В любом случае, я бы опубликовал это как проблему Go и посмотрел, что они скажут:http://code.google.com/p/go/issues/list
Пересмотр предыдущего ответа.
Поисковый API-метод Twitter Trends response представлен в удобной канонической и нормализованной форме JSON:
{"trends":[{"name":"#amazonfail","url":"http:\/\/search.twitter.com\/search?q=%23amazonfail"},... truncated ...],"as_of":"Mon, 13 Apr 2009 20:48:29 +0000"}
Однако методы Twitter Search API trends текущие, ежедневные и еженедельные ответы представлены в неоправданно неудобной форме JSON, аналогичной:
{"trends":{"2009-03-19 21:00":[{"query":"AIG","name":"AIG"},... truncated ...],... truncated ...},"as_of":1239656409}
В явном нарушении правил инкапсуляции алгоритмов и структур данных это излишне раскрывает, что в настоящее время эти методы используют карту или словарь для своей реализации.
Чтобы прочитать данные JSON из Текущие тенденции Twitter в Go data structures, используя пакет 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)
}