0

バックエンドが次のようなオブジェクトを返す (迷惑な) 状況があります。

{
"user": {
        "name": [
            "John"
        ],
        "familyName": [
            "Johnson"
        ]
    }
}

ここで、各プロパティは、最初の要素として文字列を保持する配列です。私のデータ モデルstructでは、各プロパティを配列として宣言できましたが、それは実際には醜いものです。私は自分のモデルをそのようにしたいと思います:

struct User: Codable {
    var user: String
    var familyName: String
}

ただし、これはもちろん、型が一致しないため、エンコード/デコードに失敗します。これまで、オブジェクトとプロパティObjectMapperを提供するライブラリを使用してきました。これにより、プロパティを型として宣言し、モデルメソッドでこの関数を介して各値を割り当てることができました。MapcurrentValueStringinit

extension Map {
    public func firstFromArray<T>(key: String) -> T? {
        if let array = self[key].currentValue as? [T] {
            return array.first
        }
        return self[key].currentValue as? T
    }
}

しかしCodable、私はアプローチに変換しているので、そのようなマッピングを行う方法がわかりません。何か案は?

4

2 に答える 2

2

オーバーライドできますinit(from decoder: Decoder):

let json = """
{
    "user": {
        "name": [
        "John"
        ],
        "familyName": [
        "Johnson"
        ]
    }
}
"""

struct User: Codable {
    var name: String
    var familyName: String

    init(from decoder: Decoder) throws {
        let container:KeyedDecodingContainer = try decoder.container(keyedBy: CodingKeys.self)
        let nameArray = try container.decode([String].self, forKey: .name)
        let familyNameArray = try container.decode([String].self, forKey: .familyName)
        self.name = nameArray.first!
        self.familyName = familyNameArray.first!
    }

    enum CodingKeys: String, CodingKey {
        case name
        case familyName
    }
}

let data = json.data(using: .utf8)!
let decodedDictionary = try JSONDecoder().decode(Dictionary<String, User>.self, from: data)
print(decodedDictionary) // ["user": __lldb_expr_48.User(name: "John", familyName: "Johnson")]

let encodedData = try JSONEncoder().encode(decodedDictionary["user"]!)
let encodedStr = String(data: encodedData, encoding: .utf8)
print(encodedStr!) // {"name":"John","familyName":"Johnson"}
于 2017-11-21T17:50:57.837 に答える