我有一个API,它有时会以Int的形式返回JSON中的特定键值(在本例中为id
),有时会以String的形式返回相同的键值。如何使用codable来解析JSON?
struct GeneralProduct: Codable {
var price: Double!
var id: String?
var name: String!
private enum CodingKeys: String, CodingKey {
case price = "p"
case id = "i"
case name = "n"
}
init(price: Double? = nil, id: String? = nil, name: String? = nil) {
self.price = price
self.id = id
self.name = name
}
}
我一直收到这个错误消息:Expected to decode String but found a number instead
。它返回一个数字的原因是因为id字段为空,当id字段为空时,它默认返回0作为codable标识为数字的ID。我基本上可以忽略ID键,但codable并没有给予我忽略它的选项。处理这件事的最好办法是什么?
这里是JSON。超级简单
工作
{
"p":2.12,
"i":"3k3mkfnk3",
"n":"Blue Shirt"
}
错误-因为系统中没有id,它返回0作为默认值,codable显然将其视为数字而不是字符串。
{
"p":2.19,
"i":0,
"n":"Black Shirt"
}
6条答案
按热度按时间n3h0vuf21#
编辑/更新:
当API返回
0
时,您也可以简单地将nil
分配给您的id
:3yhwsihp2#
这是
MetadataType
的一个可能的解决方案,好的一面是,它不仅可以是GeneralProduct
的通用解决方案,而且可以是所有具有相同模糊性的struct
的通用解决方案:这是一个测试:
pnwntuvh3#
从
Int
或String
无错误地解码为相同的属性需要编写一些代码。然而,由于语言中的一个(有点)新的添加,(属性 Package 器),你可以很容易地在任何你需要的地方重用这个逻辑:
属性 Package 器及其支持代码可以这样实现:
原始答案
你可以在一个字符串上使用一个 Package 器,它知道如何从任何基本的JSON数据类型解码:string,number,boolean:
然后,您可以在结构中使用此新类型。一个小缺点是,结构的使用者需要进行另一个间接访问来访问 Package 的字符串。但是,可以通过将解码后的
RelaxedString
属性声明为private来避免这种情况,并为public接口使用计算的属性:上述方法的优点:
1.不需要编写自定义的
init(from decoder: Decoder)
代码,如果要解码的属性数量增加,1.可重用性-
RelaxedString
可以无缝地用于其他结构GeneralProduct
的消费者不知道/关心id可以来自字符串或int。1.公共接口公开字符串值,这使消费者代码保持简单,因为它不必处理多种类型的数据
flseospp4#
我创建了这个Gist,它有一个ValueWrapper结构,可以处理以下类型
https://gist.github.com/amrangry/89097b86514b3477cae79dd28bba3f23
cgyqldqp5#
根据@Cristik的回答,我提出了另一个使用
@propertyWrapper
的解决方案。使用是
我想-
wz3gfoph6#
你可以用这个pod https://github.com/muhammadali2012/Model
简单地将这些属性 Package 器添加到类型不确定的可编码属性上。ie
你会得到id作为字符串,即使你从JSON中得到int,甚至nill,甚至key不存在。