20505


Go言語を使って構造体を定義し、下記レスポンスをUnmarshalでパースしたいです。`authors`のところが数字をキーとして使用しています。

[https://glosbe.com/gapi/translate?from=en&dest=ja&format=json&phrase=test&pretty=true](https://glosbe.com/gapi/translate?from=en&dest=ja&format=json&phrase=test&pretty=true)

以前コチラの質問で`simple-
json`でのパースについて質問させていただきましたが、標準ライブラリのUnmarshalではどのようにすればいいのでしょうか。`json:"-"`を指定すればフィールドを無視できるようですが、その時構造体の要素はどのように定義すればいいでしょうか。

[キーが変動するJsonをパースしたい](https://ja.stackoverflow.com/questions/19393/%E3%82%AD%E3%83%BC%E3%81%8C%E5%A4%89%E5%8B%95%E3%81%99%E3%82%8Bjson%E3%82%92%E3%83%91%E3%83%BC%E3%82%B9%E3%81%97%E3%81%9F%E3%81%84)


CC BY-SA 3.0
2015-12-31T04:29:34.280
20497
2015-12-31T14:36:02.550
2017-04-13T12:52:38.920
-1
7232
question
go json api
Goで数字がキーのJsonをUnmarshalしたい


参考情報ですが

厳密にはJSONではkeyに数字を使えず、文字列しか使えないそうです。

[JavaScript Object Notation -
Wikipedia](https://ja.wikipedia.org/wiki/JavaScript_Object_Notation#.E8.A1.A8.E8.A8.98.E6.96.B9.E6.B3.95)

> ここで注意することはキーとして使うデータ型は文字列に限ることである。


CC BY-SA 3.0
2015-12-31T06:17:30.227
20502
2015-12-31T06:17:30.227
5246
20497
answer


まず、`tuc.authors`(下記プログラム内の `TucItem.Authors` に対応)を `interface{}` 型で
unmarshaling します。レスポンス(JSON format)の最後に `authors` タグがあるので、これを map に取り込んで先の
`TucItem.Authors` にマッチングさせて、`Author` 型のデータに入れ替えます(対応するデータがない場合は `nil`
が入ります)。ただ、`interface{}` 型なので必要に応じて type assertion を行う事になります。

[code]

    package main
    
    import (
      "encoding/json"
      "fmt"
      "io/ioutil"
      "net/http"
      "net/url"
      "strconv"
    )
    
    type Translate struct {
      Result  string
      Tuc     []TucItem
      Phrase  string
      From    string
      Dest    string
      Authors map[string]Author
    }
    
    type TucItem struct {
      Phrase    PhraseItem
      Meanings  []PhraseItem
      MeaningId float64
      Authors   []interface{}
    }
    
    type PhraseItem struct {
      Text     string
      Language string
    }
    
    type Author struct {
      U   string
      Id  uint
      N   string
      Url string
    }
    
    func main() {
      values := url.Values{}
      values.Add("format", "json")
      values.Add("from", "en")
      values.Add("dest", "ja")
      values.Add("phrase", "test")
    
      resp, err := http.Get("https://glosbe.com/gapi/translate?" + values.Encode())
      if err != nil {
        fmt.Println(err)
      }
    
      defer resp.Body.Close()
      rf, err := ioutil.ReadAll(resp.Body)
      if err != nil {
        fmt.Println(err)
      }
    
      var result Translate
      json.Unmarshal(rf, &result)
    
      // Replace authors data
      for _, tuc := range result.Tuc {
        for i, id := range tuc.Authors {
          aid := int(id.(float64))
          v, ok := result.Authors[strconv.Itoa(aid)]
          if ok {
            tuc.Authors[i] = v
          } else {
            tuc.Authors[i] = nil
          }
        }
      }
    
      // Show authors
      for _, tuc := range result.Tuc {
        text := tuc.Phrase.Text
        if len(text) == 0 {
          text = tuc.Meanings[0].Text[0:5] + "..."
        }
        fmt.Printf("%s:", text)
        for _, author := range tuc.Authors {
          fmt.Printf(" %#v", author)
        }
        fmt.Println("")
      }
    }
    
[/code]


CC BY-SA 3.0
2015-12-31T08:17:08.450
20505
2015-12-31T14:36:02.550
2015-12-31T14:36:02.550
20497
answer