使用可编码的值,有时是 Int,有时是 String
我有一个 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
}
}
我不断收到此错误消息:预期解码字符串,但发现了一个数字
。它返回数字的原因是因为 id 字段为空,当 id 字段为空时,它默认返回 0 作为 ID,可编码识别为数字。我基本上可以忽略 ID 密钥,但据我所知,可编码并没有给我忽略它的选项。处理这个问题的最佳方法是什么?
这是 JSON。这是超级简单的
工作
{
"p":2.12,
"i":"3k3mkfnk3",
"n":"Blue Shirt"
}
错误 - 因为系统中没有 id,所以它默认返回 0,可编码显然将其视为与字符串相反的数字。
{
"p":2.19,
"i":0,
"n":"Black Shirt"
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
编辑/更新:
当您的 api 返回
0
时,您也可以简单地将nil
分配给您的id
:edit/update:
You can also simply assign
nil
to yourid
when your api returns0
:这是
MetadataType
的一个可能的解决方案,好处是它可以是一个通用解决方案,不仅适用于GeneralProduct
,而且适用于所有具有以下功能的struct
同样的歧义:这是测试:
This is a possible solution with
MetadataType
, the nice thing is that can be a general solution not forGeneralProduct
only, but for all thestruct
having the same ambiguity:this is the test:
从
int
或字符串
中无缝解码为同一属性需要编写一些代码。但是,由于(属性包装纸)(属性包装器),您可以在任何需要的地方重复使用此逻辑非常容易:
属性包装器及其支持代码可以像这样实现:
原始答案
您可以通过知道如何从任何基本JSON数据类型解码的字符串上使用包装器:字符串,数字,布尔值:
然后,您可以在结构中使用此新类型。一个较小的缺点是结构的消费者需要进行另一个间接的访问以访问包裹的字符串。但是,可以通过将解码的
放松
属性为私有来避免这种避免,并在公共接口中使用计算的属性:上述方法的优点:
Init(来自解码器::解码器)
代码,如果要解码的属性数量增加可重复可以在其他结构中无缝地使用
GeneralProduct
的消费者不知道/关心ID可以来自字符串或intSeamlessly decoding from either
Int
orString
into the same property requires writing some code.However, thanks to a (somewhat) new addition to the language,(property wrappers), you can make it quite easy to reuse this logic wherever you need it:
The property wrapper and its supporting code can be implemented like this:
Original answer
You can use a wrapper over a string that knows how to decode from any of the basic JSON data types: string, number, boolean:
You can then use this new type in your struct. One minor disadvantage would be that consumer of the struct will need to make another indirection to access the wrapped string. However that can be avoided by declaring the decoded
RelaxedString
property as private, and use a computed one for the public interface:Advantages of the above approach:
init(from decoder: Decoder)
code, which can become tedious if the number of properties to be decoded increaseRelaxedString
can be seamlessly used in other structsGeneralProduct
don't know/care that the id can come from a string or an int我创建了这个 Gist,它有一个 ValueWrapper 结构可以处理
以下类型
https://gist.github.com/amrangry/89097b86514b3477cae79dd28bba3f23
I created this Gist which has a ValueWrapper struct that can handle
the following types
https://gist.github.com/amrangry/89097b86514b3477cae79dd28bba3f23
根据@cristik的答案,我使用
@propertywrapper
提供了另一种解决方案。用法也
像-i认为 -
Based on @Cristik 's answer, I come with another solution using
@propertyWrapper
.And usage is
Also works like -I think-
您可以使用此 pod https://github.com/muhammadali2012/Model
只需将这些属性包装器添加到您的可编码属性的类型不确定。即,
即使您从 JSON 中获取 int 或什至 nill 或即使 key 不存在,您也会获得 String 形式的 id。
you can use this pod https://github.com/muhammadali2012/Model
Simply add these property wrappers on your codable properties which type is not sure. ie
you will get id as String even if you get int from JSON or even nill or even if key doesn't exist.