iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 22
1
Modern Web

從無到有,使用 Go 開發應用程式系列 第 22

Parse JSON

昨天把網頁載好,不過裡面的資料似乎很難處理。後來有找到另一個 API :

https://www.moedict.tw/a/字.json

它會回傳 JSON 格式的字串,解析簡單很多。而 YAML 套件也能解析 JSON ,直接上吧!

開工

首先先把 URL 改掉:

const (
	dictionary = `https://www.moedict.tw/a/%s.json`
)

呼叫改使用 fmt.Sprintf()

req := goreq.Request{
    Uri: fmt.Sprintf(dictionary, string(word)),
}

這樣執行應該回傳就會變成 JSON 格式了。

下一步是要把 JSON 轉成 go 的資料型態,這次的結構就很鬆散了,改用 Map 做會比較簡單:

type MoeDict struct {
	Heteronyms []Heteronym
}

type Heteronym struct {
	Definitions []string
}

func convertJsonToStruct(json string) (dict MoeDict, err error) {
	m := make(map[interface{}]interface{})
	yaml.Unmarshal([]byte(json), &m)

	heteronyms := convertHeteronyms(m["h"])

	return MoeDict{heteronyms}, err
}

func convertSliceMap(sliceMap []interface{}) (sm []map[interface{}]interface{}) {
	for _, m := range sliceMap {
		sm = append(sm, m.(map[interface{}]interface{}))
	}

	return sm
}

func convertHeteronyms(in interface{}) (out []Heteronym) {
	heteronyms := convertSliceMap(in.([]interface{}))

	for _, heteronym := range heteronyms {
		definitions := convertDefinitions(heteronym["d"])

		out = append(out, Heteronym{
			definitions,
		})
	}

	return
}

func convertDefinitions(in interface{}) (out []string) {
	definitions := convertSliceMap(in.([]interface{}))

	for _, definition := range definitions {
		def := convertDef(definition["f"].(string))

		out = append(out, def)
	}

	return
}

func convertDef(in string) string {
	def := in

	def = strings.Replace(def, "~", "", -1)
	def = strings.Replace(def, "`", "", -1)

	return def
}

因為原始資料的設計是多讀音配多種解釋,會是樹狀結構加一堆陣列,所以必須要很多 for 來處理。

而 QueryCommand 改寫成這樣:

dict, err := provider.Query(str)

for _, heteronym := range dict.Heteronyms {
    for _, definition := range heteronym.Definitions {
        fmt.Println(definition)
    }
}

展示

$ go run main.go query 萌
草木初生的芽。
事物發生的開端或徵兆。
人民。
姓。如五代時蜀有萌慮。
發芽。
發生。

目前沒把讀音做篩選,不過這樣也感覺蠻有樣子了。

程式碼可以參考 PR Day 22

參考資料


上一篇
Send HTTP Request
下一篇
HTTP Server
系列文
從無到有,使用 Go 開發應用程式30

尚未有邦友留言

立即登入留言