LoginSignup
29
29

More than 5 years have passed since last update.

構造を定義したJSONを安全に扱うSwiftコードを自動生成する

Posted at

はじめに

Swiftで任意の形式のJSONを扱うには Swiftで面倒なJSONの取り扱いをさらに10倍便利にするclass JSON がかなり便利です。

しかし、大抵のAPIなどで得られるJSONは既に構造が決まっていて、そのやりとりやその後の処理を記述する部分では、可能ならば型安全の恩恵を受けたいと思うことがあります。

Json Schema というのはそういう方向性なのかもしれませんが、無駄に大きいというか、現状ちょっと扱いづらい。

ということで、↓こういうオレオレコードジェネレータを作ったのでご紹介します。
https://github.com/mokemokechicken/ObjectJsonMapperGenerator

使い方

次のStepです。

  • JSONの構造を定義する
  • それからSwiftコードを自動生成する
  • 使う

JSONの構造を定義する

JSONの構造をYAMLで定義します。
例えば、こんな感じです。

book.yml
Book:
  authors: [Author]
  title: String
  year: Int
  note?: String
  price: Double
  option?:
    hoge?: String
    hara?: Bool

Author:
  name: String
  others?: [Book]
  • Entityを定義していきます。定義したEntityも構造に含むことができます。
  • そのKeyがOptionの時は Key名の後ろに ? を付けます。Swift風ですが、この書き方は簡潔で気に入っています。
  • Arrayは Swift的に [型] で表します。
  • ただ、 ArrayのArrayは作れません
    • 何故か?実装がややこしくて… 使わないだろうしドンマイです。
    • どうしてもというときは、ダミーのEntityでも間に挟むということで…

それからSwiftコードを自動生成する

上記のProjectをCloneして、 bin/make_ojm.rb を実行します。こんな感じです。

git clone https://github.com/mokemokechicken/ObjectJsonMapperGenerator.git
cd ObjectJsonMapperGenerator
ruby bin/make_ojm.rb -l swift -c book.yml > Book.swift

この Book.swift に 上記の構造のJSONをシリアライズ・デシリアライズするコードが生成されます。

ちなみに、現時点では↓こんなコードになります。
https://gist.github.com/mokemokechicken/2fae3969dcfaeb09aa18

使う

こんな感じに使います。

let data = NSData(contentsOfFile: "path/to/json")!

if let book = Book.fromData(data) {   // 読み込み
    println("Title: \(book.title), Price: $\(book.price)")
    println(book.toJsonString())    // JSONにする
} else { 
    // 定義された構造として読み込みできなかった
    println("JSON Parse Error")
}

今回の仕様として、定義された構造としてJSONをParseできない場合は、nil を返します。
Swiftには例外機構がない(ないですよね?)ので、Parseの深い部分でエラーがあるときに、そこから延々とnilをChainして戻していく必要がありました。なので生成されたコードは結構野暮ったいです。
ん〜もっと良い書き方は無かったのかな。。。

余談

  • 日付や時刻型欲しい! という場合は、 extensionなどで拡張してもらう方向で考えています。
  • Validation とかも extension で記述していく方向で良いのかな。
  • EntityのBaseとなるClassにNSObjectを継承させるかは迷っています。
  • 簡単な動作検証用Xcode Project → https://github.com/mokemokechicken/ObjectJsonMappingSwiftTest

さいごに

この続きでAPI通信する部分も自動生成したいな、と思っています。
Java版もいつか作りたいですが、Swift版がある程度落ち着いてからかな。

29
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
29