はじめに
Swift4からCodableを使ってJsonを簡単に扱えるようになりました。
ゲームのマルチプレイを実装する上で、float3をJsonで送る必要がありました。
そこで、float3をCodableに対応させました。
Codableに対応させるということ
Codableに対応させるためには、Encodableプロトコルと、Decodableプロトコルに対応させる必要があります。
実装方法
Encodable, Decodableプロトコルに対応させるためにContainerに入れるのですが、KeyedContainer, SingleValueContainer, UnkeyedContainerの3つがあります。
Jsonをエンコード、デコードするコード
JSONEncoderとJSONDecoderを使ってCodableに対応したJsonに変換します。
struct Message: Codable {
var result: Bool
var position: float3
}
do {
let msg = Message(result: true, position: float3(1.2, 3.4, -5.1))
let data = try JSONEncoder().encode(msg)
let jsonString = String(data: data, encoding: .utf8)
print("string : ", jsonString!)
let msg2 = try JSONDecoder().decode(Message.self, from: data)
print("Message : ", msg2)
} catch {
print("err json")
}
KeyedContainer
キー値を使ってデータを保存
extension float3: Codable {
private enum ElementKeys:String, CodingKey {
case x, y, z
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: ElementKeys.self)
try container.encode(x, forKey: .x)
try container.encode(y, forKey: .y)
try container.encode(z, forKey: .z)
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ElementKeys.self)
let _x = try container.decode(Float.self, forKey: .x)
let _y = try container.decode(Float.self, forKey: .y)
let _z = try container.decode(Float.self, forKey: .z)
self.init(_x, _y, _z)
}
}
jsonに出力した結果↓
{"result":true,"position":{"x":1.2000000476837158,"y":3.4000000953674316,"z":3.4000000953674316}}
SingleValueContainer
1つのデータを送りる
extension float3: Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(x)
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let _x = try container.decode(Float.self)
self.init(_x, 0.0, 0.0)
}
}
jsonに出力した結果↓
{"result":true,"position":1.2000000476837158}
UnkeyedContainer
配列形式のデータになる
extension float3: Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
for v in self {
try container.encode(v)
}
}
public init(from decoder: Decoder) throws {
var arr = [Float]()
var unkeyedContainer = try decoder.unkeyedContainer()
while !unkeyedContainer.isAtEnd {
arr.append(try unkeyedContainer.decode(Float.self))
}
self.init(arr)
}
}
jsonに出力した結果↓
{"result":true,"position":[1.2000000476837158,3.4000000953674316,-5.0999999046325684]}
終わりに
Codableは簡単にJsonにエンコード、デコードできるので便利です。