今日、マイクロソフト本社から来た David さんとお昼ご飯をしたときに教えてもらえた彼のプロダクトが凄かったので紹介したいと思います。
quicktype
JSON をペーストするとシリアライズ・デシリアライズするためのコードを出力してくれるサービスです。
例えば、以下のような JSON があるとします。
{ "name": "Kazuki Ota", "age": 36, "pets": [ { "name": "hoge" }, { "name": "foo" } ] }
ページに張り付けるとこういうコードが生成されます。
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: // // using Sample.Models; // // var data = Person.FromJson(jsonString); // namespace Sample.Models { using System; using System.Net; using System.Collections.Generic; using Newtonsoft.Json; public partial class Person { [JsonProperty("age")] public long Age { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("pets")] public Pet[] Pets { get; set; } } public partial class Pet { [JsonProperty("name")] public string Name { get; set; } } public partial class Person { public static Person FromJson(string json) => JsonConvert.DeserializeObject<Person>(json, Converter.Settings); } public static class Serialize { public static string ToJson(this Person self) => JsonConvert.SerializeObject(self, Converter.Settings); } public class Converter { public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings { MetadataPropertyHandling = MetadataPropertyHandling.Ignore, DateParseHandling = DateParseHandling.None, }; } }
画面はこんな感じです。使い方に迷うことはないと思われる。
Visual Studio にも組み込みで JSON からコードを生成する機能があるのですが、ルートのクラス名が決めれなかったり、プロパティ名が JSON のプロパティ名と同じになるので小文字から始まるプロパティになったりしてもんにょりするのですが、そこらへんがきっちり考えられてる!!
今回は、C# の出力コード例を示しましたが他の言語にも対応しています。
- Swift
- TypeScript
- Go
- C#
- Java
- etc...
例えば TypeScript だとこういう感じになります。
// To parse this data: // // import { Convert, Person } from "./file"; // // const person = Convert.toPerson(json); export interface Person { age: number; name: string; pets: Pet[]; } export interface Pet { name: string; } // Converts JSON strings to/from your types export module Convert { export function toPerson(json: string): Person { return JSON.parse(json); } export function personToJson(value: Person): string { return JSON.stringify(value, null, 2); } }
quicktype は本当に賢くて、以下のように複数の型が入り混じった配列の JSON を渡すと…
{ "items": [ "a", "b", 3 ] }
ちゃんと型をいい感じにしてくれます。
// To parse this data: // // import { Convert, Person } from "./file"; // // const person = Convert.toPerson(json); export interface Person { items: Array<number | string>; } // Converts JSON strings to/from your types export module Convert { export function toPerson(json: string): Person { return JSON.parse(json); } export function personToJson(value: Person): string { return JSON.stringify(value, null, 2); } }
このパワーをローカルで
サイトの下の方に気になる1文が書いてあります。
npm i -g quicktype
ということで nodejs は導入済みなので、ターミナルを開いてうってみました。
C:\Users\xxxxx>npm i -g quicktype C:\Users\xxxxx\AppData\Roaming\npm\quicktype -> C:\Users\xxxxx\AppData\Roaming\npm\node_modules\quicktype\quicktype.js + quicktype@3.3.0 updated 1 package in 2.711s
入った!quicktype と打ち込むと使い方が出てきます。共通のオプションと C# の部分だけ抜粋してみました。
Synopsis $ quicktype [--lang cs|go|c++|java|ts|swift|elm|schema|types] FILE|URL ... Description Given JSON sample data, quicktype outputs code for working with that data in C#, Go, C++, Java, TypeScript, Swift, Elm, JSON Schema, Simple Types. Options -o, --out FILE The output file. Determines --lang and --top-level. -t, --top-level NAME The name for the top level type. -l, --lang cs|go|c++|java|ts|swift|elm|schema|types The target language. -s, --src-lang json|schema The source language (default is json). --src FILE|URL|DIRECTORY The file, url, or data directory to type. --src-urls FILE Tracery grammar describing URLs to crawl. --no-combine-classes Don't combine similar classes. --no-maps Don't infer maps, always use classes. --quiet Don't show issues in the generated code. -h, --help Get some help. Options for C# --namespace NAME Generated namespace --csharp-version 6|5 C# version --density normal|dense Property density --array-type array|list Use T[] or List<T> --features complete|attributes-only|just-types Output features
なんとなくわかる。コマンドから動けばこっちのもんですよね。例えば Visual Studio 2017 で適当なプロジェクトを作ります。
そして、適当な JSON を準備します。ここら辺のを使ってみようかな。Swagger(Open API) のファイルっぽい。
プロジェクトの下に datasources フォルダを作って petstore.url というファイルを作って上記サイトの JSON の Raw データへの URL をぺたっと貼ります。プロジェクトはこんな感じになりました。
プロジェクトのプロパティのビルド前イベントのコマンドラインに以下のようなコマンドを書いておきます。単純に qicktype コマンドを書いてるだけですね。フォルダを指定するだけで、そこにある json や url ファイルを対象にしてくれます。
quicktype $(ProjectDir)datasources -o $(ProjectDir)Entities\Petstore.cs --namespace QuickTypeDemo.Entities --csharp-version 6 --features complete
ビルドして、プロジェクトですべてのファイルを表示すると確かに出来上がってることが確認できます。
プロジェクトに追加しておきましょう。こんなにたくさん(まだ下に続いてます)クラスを生成してくれました。
JSON.NET を参照に追加して、以下のようなコードを書いてみました。
using QuickTypeDemo.Entities; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace QuickTypeDemo { class Program { static void Main(string[] args) { var json = new HttpClient().GetStringAsync("https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/json/petstore.json").Result; var petstore = Petstore.FromJson(json); Console.WriteLine(petstore.Info.Title); } } }
ブレークポイントで止めてみたら、ちゃんと読み込めてることがわかりますね。
他にも
Xcode と VSCode で使う方法は公式の Blog に記事があります。
さらに、今回はコマンドをビルドアクションで叩く感じでやりましたが、IDE などのツールとのインテグレーションは考えられてるみたいです。素敵!!
IDE/editor integration
まとめ
JSON を格納するための型定義にお悩みの人は試してみるといいと思いました!凄い!賢い! 個人的に、今まで触ってきた JSON をパースしてクラス定義を出力してくれるほかのサービスと比べて断然使いやすいと思いました。ローカルコマンドが提供されてるのもあついですね。
IDE やエディタとの連携が本当にシームレスになるとやばいことになりそうな気がします。