Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?

More than 3 years have passed since last update.

@fuziki

float3をCodableに対応させる(Swift4)

はじめに

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にエンコード、デコードできるので便利です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
4
Help us understand the problem. What is going on with this article?