LoginSignup
1
1

More than 1 year has passed since last update.

SwiftでProtocolの配列をプロパティに持つオブジェクトをJSONにencodeする

Last updated at Posted at 2022-11-17

概要

タイトルの通り、以下のようなJSONをencodeしようとしてハマったため、こちらの記事に簡単にメモしておきます。

{
    "value": 5,
    "list": [
        {
            "className": "A"
        },
        {
            "className": "B"
        }
    ]
}

実装例。containerをネストさせます。

import Foundation

protocol P : Encodable {}

class A : P {
    var className = "A"
}

class B : P {
    var className = "B"
}

class Data : Encodable {

    var value: Int = 5
    
    var list: Array<P> = [A(), B()]

    public func encode(to encoder: Encoder) throws {
        var rootContainer = encoder.container(keyedBy: CodingKeys.self)
        try rootContainer.encode(value, forKey: .value)

        var listContainer = rootContainer.nestedUnkeyedContainer(forKey: .list)
        for p in list {
            try listContainer.encode(p)
        }
    }

    enum CodingKeys: String, CodingKey {
        case value
        case list
    }
}


let data = try JSONEncoder().encode(Data())
print(String(data: data, encoding: .utf8)!)
// -> {"value":5,"list":[{"className":"A"},{"className":"B"}]}

検索用 エラーの例

error: type 'any P' cannot conform to 'Encodable'
        try rootContainer.encode(list, forKey: .list)

note: only concrete types such as structs, enums and classes can conform to protocols
        try rootContainer.encode(list, forKey: .list)

note: requirement from conditional conformance of 'Array<any P>' to 'Encodable'
        try rootContainer.encode(list, forKey: .list)
1
1
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
1
1