ついに TinyGo で enconding/json が使えるようになったので試してみた

遠くない未来にリリースされる TinyGo 0.28 は reflect package の互換性がかなり改善しています。

さらりと書きましたが、こんな感じでものすごい commit が登録されています。 軽く reflect で検索するだけで 113 commit という凄さ。 reflect で検索されない reflect 関連の commit もあるので、本当にハードワークだった感じです。

$ git log v0.27.0..dev --oneline | wc -l                                                                                       
319                                                                                                                            
                                                                                                                               
$ git log v0.27.0..dev --oneline | grep reflect | wc -l                                                                        
113                                                                                                                            

ということで、 reflect package の改善により encoding/json がかなり使えるようになったので試してみましょう。

簡単な JSON

TinyGo に含まれる targets/wioterminal.json を更に小さくした JSON で試してみました。

gist.github.com

結果はこんな感じで、普通に正しく実行できます。

$ tinygo run .
{"build-tags":["wioterminal"],"flash-method":"msd"}

ちょっと複雑な JSON

先程の例は簡単すぎるので、もう少し複雑な例を試してみます。 Twitter API の説明ページにあった JSON を Marshall / Unmashall してみます。

// https://developer.twitter.com/en/docs/twitter-api/v1/data-dictionary/overview
const twitterJSON = `
{
  "created_at": "Thu Apr 06 15:24:15 +0000 2017",
  "id_str": "850006245121695744",
  "text": "1\/ Today we\u2019re sharing our vision for the future of the Twitter API platform!\nhttps:\/\/t.co\/XweGngmxlP",
  "user": {
    "id": 2244994945,
    "name": "Twitter Dev",
    "screen_name": "TwitterDev",
    "location": "Internet",
    "url": "https:\/\/dev.twitter.com\/",
    "description": "Your official source for Twitter Platform news, updates & events. Need technical help? Visit https:\/\/twittercommunity.com\/ #TapIntoTwitter"
  },
  "place": {   
  },
  "entities": {
    "hashtags": [      
    ],
    "urls": [
      {
        "url": "https:\/\/t.co\/XweGngmxlP",
        "unwound": {
          "url": "https:\/\/cards.twitter.com\/cards\/18ce53wgo4h\/3xo1c",
          "title": "Building the Future of the Twitter API Platform"
        }
      }
    ],
    "user_mentions": [     
    ]
  }
}
`

struct は以下の通り。

// https://mholt.github.io/json-to-go/
type AutoGenerated struct {
    CreatedAt string   `json:"created_at"`
    IDStr     string   `json:"id_str"`
    Text      string   `json:"text"`
    User      User     `json:"user"`
    Place     Place    `json:"place"`
    Entities  Entities `json:"entities"`
}
type User struct {
    ID          int64  `json:"id"`
    Name        string `json:"name"`
    ScreenName  string `json:"screen_name"`
    Location    string `json:"location"`
    URL         string `json:"url"`
    Description string `json:"description"`
}
type Place struct {
}
type Unwound struct {
    URL   string `json:"url"`
    Title string `json:"title"`
}
type Urls struct {
    URL     string  `json:"url"`
    Unwound Unwound `json:"unwound"`
}
type Entities struct {
    Hashtags     []any  `json:"hashtags"`
    Urls         []Urls `json:"urls"`
    UserMentions []any  `json:"user_mentions"`
}

結果は以下の通り。 正しく処理され Go で実行したものと同じ結果になります。

$ tinygo run .
{"created_at":"Thu Apr 06 15:24:15 +0000 2017","id_str":"850006245121695744","text":"1/ Today we’re sharing our vision for the future of the Twitter API platform!\nhttps://t.co/XweGngmxlP","user":{"id":2244994945,"name":"Twitter Dev","screen_name":"TwitterDev","location":"Internet","url":"https://dev.twitter.com/","description":"Your official source for Twitter Platform news, updates \u0026 events. Need technical help? Visit https://twittercommunity.com/ #TapIntoTwitter"},"place":{},"entities":{"hashtags":[],"urls":[{"url":"https://t.co/XweGngmxlP","unwound":{"url":"https://cards.twitter.com/cards/18ce53wgo4h/3xo1c","title":"Building the Future of the Twitter API Platform"}}],"user_mentions":[]}}

ソースコード全体は以下にあります。

まとめ

ということで、 TinyGo 0.28 の encoding/json は良い感じに動くと思います。 encoding/json が辛くて TinyGo を諦めていた人もいるかと思いますが、 TinyGo 0.28 がリリースされたらぜひ試してみてください。

なお、 encoding/json は激しく再帰呼出しとなって stack をかなり消費します。 マイコンで実装するときは、 --stack-size 10KB のような形で stack を増やすなどが必要になるかもしれません。

おまけ

dev branch 版をダウンロードして試すこともできます。 以下の記事を参考にしてください。

qiita.com