将数组元素映射到字符串的可编码对象



我有一个(烦人的)情况,我的后端返回一个这样的对象:

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

其中每个属性都是一个数组,该数组将字符串作为其第一个元素。在我的数据模型中struct我可以将每个属性声明为数组,但这确实很丑陋。我想让我的模型是这样的:

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

但这当然会使编码/解码失败,因为类型不匹配。到目前为止,我一直使用ObjectMapper库,它提供了一个Map对象和currentValue属性,这样我就可以将我的属性声明为String类型,并在我的模型中init方法通过这个函数确定每个值:

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方法,我不知道如何进行此类映射。有什么想法吗?

您可以覆盖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"}

我倾向于使您的模型适应传入的数据并创建用于应用程序的计算属性,例如

struct User: Codable {
var user: [String]
var familyName: [String]
var userFirstName: String? {
return user.first
}
var userFamilyName: String? {
return familyName.first
}
}

这使您可以轻松地维护数据结构的模仿,而无需覆盖编码/解码的维护成本。

如果它与您的设计相得益彰,您还可以使用UI包装器类型或视图模型,以更清楚地将基础模型与其显示区分开来。

相关内容

  • 没有找到相关文章

最新更新