Slide 1

Slide 1 text

XMLのObject Mapping Yahoo! JAPAN 森洋之

Slide 2

Slide 2 text

森 洋之 @moridroid

Slide 3

Slide 3 text

森 洋之 @moridroid Yahoo! JAPAN Androidアプリ黒帯  (こういうところで話す仕事)

Slide 4

Slide 4 text

森 洋之 @moridroid Yahoo! JAPAN Androidアプリ黒帯  (こういうところで話す仕事) ヤフオク!のアプリ担当

Slide 5

Slide 5 text

goo.gl/fW2YPh

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

はじめます

Slide 8

Slide 8 text

Codable

Slide 9

Slide 9 text

{ "name": "hoge", "sex": 0, "birthday": "19900530", "mail_address": "[email protected]" } struct User: Codable { let name: String let sex: Int let birthday: String let mail_address: String } JSON struct

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

Gson

Slide 13

Slide 13 text

Gson Jackson

Slide 14

Slide 14 text

Gson Jackson Moshi

Slide 15

Slide 15 text

Gson Jackson Moshi SimpleXML

Slide 16

Slide 16 text

Gson Jackson Moshi SimpleXML JAXB

Slide 17

Slide 17 text

基本的なロジック

Slide 18

Slide 18 text

Taro 18 Japan

Slide 19

Slide 19 text

User - name uninitialized - age uninitialized - locale uninitialized Taro 18 Japan val user = User( )

Slide 20

Slide 20 text

User - name ”Taro” - age uninitialized - locale uninitialized Taro 18 Japan user.name = “Taro”

Slide 21

Slide 21 text

User - name ”Taro” - age 18 - locale uninitialized Taro 18 Japan user.age = 18

Slide 22

Slide 22 text

User - name ”Taro” - age 18 - locale ”Japan” Taro 18 Japan user.locale = “Japan”

Slide 23

Slide 23 text

User - name ”Taro” - age 18 - locale ”Japan” User - name uninitialized - age uninitialized - locale uninitialized

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

data class Excellent!!

Slide 26

Slide 26 text

data class User(val name : String, val age : Int, val locale : String)

Slide 27

Slide 27 text

data class User(val name : String, val age : Int, val locale : String) コンストラクタ

Slide 28

Slide 28 text

data class User(val name : String, val age : Int, val locale : String) コンストラクタ イミュータブル

Slide 29

Slide 29 text

data class User(val name : String, val age : Int, val locale : String) コンストラクタ イミュータブル 非null

Slide 30

Slide 30 text

基本的なロジック again!!

Slide 31

Slide 31 text

User - name ”Taro” - age 18 - locale ”Japan” User - name uninitialized - age uninitialized - locale uninitialized

Slide 32

Slide 32 text

User - name ”Taro” - age 18 - locale ”Japan” User - name uninitialized - age uninitialized - locale uninitialized 空のコンストラクタ無い

Slide 33

Slide 33 text

User - name ”Taro” - age 18 - locale ”Japan” User - name uninitialized - age uninitialized - locale uninitialized イミュータブル 空のコンストラクタ無い

Slide 34

Slide 34 text

User - name ”Taro” - age 18 - locale ”Japan” User - name uninitialized - age uninitialized - locale uninitialized イミュータブル 空のコンストラクタ無い 非null

Slide 35

Slide 35 text

User - name ”Taro” - age 18 - locale ”Japan” User - name uninitialized - age uninitialized - locale uninitialized イミュータブル 空のコンストラクタ無い 非null 考え方が合わない

Slide 36

Slide 36 text

無理に使うなら

Slide 37

Slide 37 text

data class User(var name : String?, var age : Int?, var locale : String?)

Slide 38

Slide 38 text

data class User(var name : String?, var age : Int?, var locale : String?) ミュータブル

Slide 39

Slide 39 text

data class User(var name : String?, var age : Int?, var locale : String?) ミュータブル nullable

Slide 40

Slide 40 text

data class User(var name : String?, var age : Int?, var locale : String?) ミュータブル nullable 糞プロパティ 爆誕

Slide 41

Slide 41 text

じゃあどうするか

Slide 42

Slide 42 text

JSON

Slide 43

Slide 43 text

JSON Moshi

Slide 44

Slide 44 text

XML

Slide 45

Slide 45 text

XML  見なかった  ことにする

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

XML  自分で作る

Slide 48

Slide 48 text

3つのアプローチ

Slide 49

Slide 49 text

1. Reflection

Slide 50

Slide 50 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]

Slide 51

Slide 51 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]
… data class Inbox( val name : String, val mails : List) data class Mail( val title : String, val body : String, val from : User) data class User( val name : String, val address : String)

Slide 52

Slide 52 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]
… data class Inbox( val name : String, val mails : List) data class Mail( val title : String, val body : String, val from : User) data class User( val name : String, val address : String) inline fun fromXML(xml : InputStream) : T? { // ... }

Slide 53

Slide 53 text

inline fun fromXML(xml : InputStream) : T? { // ... } val inbox = fromXML(inpustStream)

Slide 54

Slide 54 text

Mail - title : String - body : String - from : User User - name : String - address : String Inbox - name : String - mail : List

Slide 55

Slide 55 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]
… index オブジェクト プロパティ 値

Slide 56

Slide 56 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]
… index オブジェクト プロパティ 値 1 Inbox - name - Mails

Slide 57

Slide 57 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]
… index オブジェクト プロパティ 値 1 Inbox - name 受信箱 - Mails

Slide 58

Slide 58 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]
… index オブジェクト プロパティ 値 1 Inbox - name 受信箱 - Mails [ ]

Slide 59

Slide 59 text

index オブジェクト プロパティ 値 1 Inbox - name 受信箱 - Mails [2] 2 Mail - title - body - User 受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]

Slide 60

Slide 60 text

index オブジェクト プロパティ 値 1 Inbox - name 受信箱 - Mails [2] 2 Mail - title - body - User 受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]

Slide 61

Slide 61 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]
… index オブジェクト プロパティ 値 1 Inbox - name 受信箱 - Mails [2] 2 Mail - title 主人がオオアリクイに … - body いきなりのメール失礼 … - User 3 3 User - name - address

Slide 62

Slide 62 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]
… index オブジェクト プロパティ 値 1 Inbox - name 受信箱 - Mails [2] 2 Mail - title 主人がオオアリクイに … - body いきなりのメール失礼 … - User 3 3 User - name - address

Slide 63

Slide 63 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]
… index オブジェクト プロパティ 値 1 Inbox - name 受信箱 - Mails [2] 2 Mail - title 主人がオオアリクイに … - body いきなりのメール失礼 … - User 3 3 User - name オオアリクイ - address [email protected]

Slide 64

Slide 64 text

受信箱 主人がオオアリクイに… いきなりのメール失礼… オオアリクイ
[email protected]
… index オブジェクト プロパティ 値 1 Inbox - name 受信箱 - Mails [2, 4, 6, ...] 2 Mail - title 主人がオオアリクイに … - body いきなりのメール失礼 … - User 3 3 User - name オオアリクイ - address [email protected] 4 Mail - title 私はチンパンジーです。 - body はじめまして。早苗と …

Slide 65

Slide 65 text

Mail - title : String - body : String - from : User User - name : String - address : String Inbox - name : String - mail : List

Slide 66

Slide 66 text

Reflection

Slide 67

Slide 67 text

Reflection Pros 作るのが楽

Slide 68

Slide 68 text

Reflection Pros 作るのが楽 Cons Reflectionであること

Slide 69

Slide 69 text

Reflection Pros 作るのが楽 Cons Reflectionであること      ・遅い      ・kotlin-reflect、でかい

Slide 70

Slide 70 text

2. APT

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

クラス追加

Slide 73

Slide 73 text

interface XMLAdapter { fun fromXml(xml : InputStream) : T? }

Slide 74

Slide 74 text

inline fun xmlAdapter( ) : XMLAdapter { // ... } interface XMLAdapter { fun fromXml() : T? }

Slide 75

Slide 75 text

data class Inbox( val name : String, val mails : List) data class Mail( val title : String, val body : String, val from : User) data class User( val name : String, val address : String)

Slide 76

Slide 76 text

@XmlClass data class Inbox( val name : String, val mails : List) @XmlClass data class Mail( val title : String, val body : String, val from : User) @XmlClass data class User( val name : String, val address : String)

Slide 77

Slide 77 text

@XmlClass data class Inbox( val name : String, val mails : List) @XmlClass data class Mail( val title : String, val body : String, val from : User) @XmlClass data class User( val name : String, val address : String) class Inbox_XmlAdapter : XmlAdapter class Mail_XmlAdapter : XmlAdapter class User_XmlAdapter : XmlAdapter

Slide 78

Slide 78 text

inline fun xmlAdapter( ) : XMLAdapter { return Class.forName(“${T::class.name}_XmlAdapter”).newInstance() }

Slide 79

Slide 79 text

val adapter = xmlAdapter() val inbox = adapter.fromXml(inputStream) inline fun xmlAdapter( ) : XMLAdapter { return Class.forName(“${T::class.name}_XmlAdapter”).newInstance() }

Slide 80

Slide 80 text

APT

Slide 81

Slide 81 text

APT Pros Reflectionじゃないこと      拡張性高め

Slide 82

Slide 82 text

APT Pros Reflectionじゃないこと      拡張性高め Cons めんどくさい      難読化したらまずい

Slide 83

Slide 83 text

3. Transform API

Slide 84

Slide 84 text

No content

Slide 85

Slide 85 text

バイトコード変換

Slide 86

Slide 86 text

goo.gl/u5XHJi

Slide 87

Slide 87 text

inline fun xmlAdapter( ) : XMLAdapter { return when(T::class) { Inbox::class -> Inbox_XmlAdapter() Mail::class -> Mail_XmlAdapter() ... } }

Slide 88

Slide 88 text

Transform API

Slide 89

Slide 89 text

Transform API Pros 難読化しても影響ない

Slide 90

Slide 90 text

Transform API Pros 難読化しても影響ない Cons 超めんどくさい      バイトコードだから…

Slide 91

Slide 91 text

まとめ

Slide 92

Slide 92 text

つくろうぜ! オブジェクトマッパー

Slide 93

Slide 93 text

No content

Slide 94

Slide 94 text

おしまい