web-dev-qa-db-ja.com

コーディング可能な構造体で計算されたプロパティを使用する方法(Swift)

データセットをシリアル化してJsonにエンコードする「コード化可能な」構造体を作成しました。計算されたプロパティがjson文字列に表示されないことを除いて、すべてがうまく機能しています。エンコード段階で計算されたプロパティを含めるにはどうすればよいですか。

例:

struct SolidObject:Codable{

    var height:Double                      = 0
    var width:Double                       = 0
    var length:Double                      = 0

    var volume:Double {
        get{
            return height * width * length
        }
    }
}

var solidObject = SolidObject()
solidObject.height = 10.2
solidObject.width = 7.3
solidObject.length = 5.0

let jsonEncoder = JSONEncoder()
do {
    let jsonData = try jsonEncoder.encode(solidObject)
    let jsonString = String(data: jsonData, encoding: .utf8)!
    print(jsonString)
} catch {
    print(error)
}

"{" width ":7.2999999999999998、" length ":5、" height ":10.199999999999999}"を出力します

7.3の代わりに7.29999 ..を使用することにも興味がありますが、私の主な質問は「このjson文字列に「ボリューム」を含めるにはどうすればよいですか」です。

12
monroo

自動化されたものに任せる代わりに、手動でエンコード/デコードする必要があります。これは、Swiftプレイグラウンドで期待どおりに機能します。

struct SolidObject: Codable {

    var height:Double                      = 0
    var width:Double                       = 0
    var length:Double                      = 0

    var volume:Double {
        get{
            return height * width * length
        }
    }

    enum CodingKeys: String, CodingKey {
        case height
        case width
        case length

        case volume
    }

    init() { }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        height = try values.decode(Double.self, forKey: .height)
        width = try values.decode(Double.self, forKey: .width)
        length = try values.decode(Double.self, forKey: .length)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(height, forKey: .height)
        try container.encode(width, forKey: .width)
        try container.encode(length, forKey: .length)

        try container.encode(volume, forKey: .volume)
    }

}

var solidObject = SolidObject()
solidObject.height = 10.2
solidObject.width = 7.3
solidObject.length = 5.0

let jsonEncoder = JSONEncoder()
do {
    let jsonData = try jsonEncoder.encode(solidObject)
    let jsonString = String(data: jsonData, encoding: .utf8)!
    print(jsonString)
} catch {
    print(error)
}
13
Mark Thormann