JSON データから TypeScript のコードを生成するには

既にある JSON データを TypeScript で扱うとき、型定義を自分で書くのは億劫ですよね。
なので、やってくれるツールを Visual Studio Code の機能拡張で探しました。
ダウンロード数の多さを参考に、それなりに使われていそうなものを2つ試してみました。

扱う JSON データを用意する

使うデータは、radiko の Web API が返してくるデータにしました。
ただ、返されるデータ形式は XML なので、JSON にする必要があります。

1つ目は、地域の放送局を返す API
https://radiko.jp/v3/station/region/full.xml

<?xml version="1.0" encoding="UTF-8" ?>
<region>
  <stations ascii_name="HOKKAIDO TOHOKU" region_id="hokkaido-tohoku" region_name="北海道・東北">
    <station><id>HBC</id>
    <name>HBCラジオ</name>
    <ascii_name>HBC RADIO</ascii_name>
    <ruby>えいちびーしーらじお</ruby>
    <areafree>1</areafree>
    <timefree>1</timefree>
〜以下略〜

2つ目は、ニッポン放送の週間番組表を返す API
https://radiko.jp/v3/program/station/weekly/LFR.xml

<?xml version="1.0" encoding="UTF-8"?>
<radiko>
	<ttl>1800</ttl>
	<srvtime>1628297768</srvtime>
	<stations>
		<station id="LFR">
		<name>ニッポン放送</name>
			<progs>
				<date>20210731</date>
					<prog id="9580196668" master_id="" ft="20210731050000" to="20210731074000" ftl="0500" tol="0740" dur="9600">
						<title>徳光和夫 とくモリ!歌謡サタデー</title>
						<url>https://www.1242.com/toku/</url>
						<url_link></url_link>
						<failed_record>0</failed_record>
						<ts_in_ng>0</ts_in_ng>
						<ts_out_ng>0</ts_out_ng>
〜以下略〜

を取得し、XML から JSON への変換には、xml-js (https://github.com/nashwaan/xml-js)を使用しました。
変換に使ったコードは以下になります。

const xml = 'Web API が返した XML';
const json = xmljs.xml2json(
  xml,
  {
    compact: true,
    spaces: 2,
  },
);

結果はそれぞれ以下の通り。

{
  "_declaration": {
    "_attributes": {
      "version": "1.0",
      "encoding": "UTF-8"
    }
  },
  "region": {
    "stations": [
      {
        "_attributes": {
          "ascii_name": "HOKKAIDO TOHOKU",
          "region_id": "hokkaido-tohoku",
          "region_name": "北海道・東北"
        },
        "station": [
          {
            "id": {
              "_text": "HBC"
            },
            "name": {
              "_text": "HBCラジオ"
            },
            "ascii_name": {
              "_text": "HBC RADIO"
            },
            "ruby": {
              "_text": "えいちびーしーらじお"
            },
            "areafree": {
              "_text": "1"
            },
            "timefree": {
              "_text": "1"
            },
〜以下略〜
{
  "_declaration": {
    "_attributes": {
      "version": "1.0",
      "encoding": "UTF-8"
    }
  },
  "radiko": {
    "ttl": {
      "_text": "1800"
    },
    "srvtime": {
      "_text": "1628299563"
    },
    "stations": {
      "station": {
        "_attributes": {
          "id": "LFR"
        },
        "name": {
          "_text": "ニッポン放送"
        },
        "progs": [
          {
            "date": {
              "_text": "20210731"
            },
            "prog": [
              {
                "_attributes": {
                  "id": "9580196668",
                  "master_id": "",
                  "ft": "20210731050000",
                  "to": "20210731074000",
                  "ftl": "0500",
                  "tol": "0740",
                  "dur": "9600"
                },
                "title": {
                  "_text": "徳光和夫 とくモリ!歌謡サタデー"
                },
                "url": {
                  "_text": "https://www.1242.com/toku/"
                },
                "url_link": {},
                "failed_record": {
                  "_text": "0"
                },
                "ts_in_ng": {
                  "_text": "0"
                },
                "ts_out_ng": {
                  "_text": "0"
                },
〜以下略〜

JSON としては無駄が目に付きますが、XML からの変換を考えると仕方ないですね。

機能拡張「JSON to TS」で変換してみた

1つ目は「JSON to TS」です。

変換するには、変換元となる JSON をコピーしてクリップボードにある状態から、Windows なら Shift + Ctrl + Alt + V、Mac なら ⌃⇧⌥V することで、TypeScript のコードが生成されました。

interface RootObject {
  _declaration: Declaration;
  region: Region;
}

interface Region {
  stations: Station2[];
}

interface Station2 {
  _attributes: Attributes2;
  station: Station[];
}
〜以下略〜

LFR.json の方は、残念ながら「spawnSync /bin/sh ENOBUFS」となり変換できませんでした。
大きいデータは無理っぽいです。

機能拡張「Paste JSON as Code」で変換してみた

2つ目は「Paste JSON as Code」です。

TypeScript の他に、変換先に Python / Go / Ruby / C# / Java / Swift / Rust / Kotlin / C++ / Flow / Objective-C / JavaScript / Elm / JSON Schema が選べます。

変換するには、変換元となる JSON をコピーしてクリップボードにある状態からコマンドパレット(Windows は Ctrl + Shift + P、Mac は ⇧⌘P)で、

  • 「Paste JSON as Code」を選択
  • 変換先に「TypeScript」を選択
  • 最上位の型名を入力

という手順になります。LFR.json をコピーした状態から、以下の様な感じです。こちらは大きくても変換できました。

変換した結果は、それぞれ以下の通り。

// Generated by https://quicktype.io

export interface Full {
  _declaration: Declaration;
  region:       Region;
}

export interface Declaration {
  _attributes: DeclarationAttributes;
}

export interface DeclarationAttributes {
  version:  string;
  encoding: string;
}
〜以下略〜
// Generated by https://quicktype.io

export interface Lfr {
  _declaration: Declaration;
  radiko:       Radiko;
}

export interface Declaration {
  _attributes: DeclarationAttributes;
}

export interface DeclarationAttributes {
  version:  string;
  encoding: string;
}
〜以下略〜

ということで今の所、私は「Paste JSON as Code」の方を使おうと思います。

プロを目指す人のためのTypeScript入門 (Amazon)

コメント