Ios 如何使用Swift JSONDecoder解码可以是数组或单个对象的JSON属性?
我试图解码JSON对象,其中一个属性可以是数组或单个对象。我的想法是引入带有Ios 如何使用Swift JSONDecoder解码可以是数组或单个对象的JSON属性?,ios,json,swift,Ios,Json,Swift,我试图解码JSON对象,其中一个属性可以是数组或单个对象。我的想法是引入带有单个和多个案例的enum。简化代码示例如下: struct Show:Codable{ var artistBio:ArtistBios? } 枚举ArtistBios:可编码{ 个案单张(ArtistBio) 多病例([ArtistBio]) init(来自解码器:解码器)抛出{ var container=try decoder.unkeydcontainer() 如果container.count!=nil{ le
单个
和多个
案例的enum。简化代码示例如下:
struct Show:Codable{
var artistBio:ArtistBios?
}
枚举ArtistBios:可编码{
个案单张(ArtistBio)
多病例([ArtistBio])
init(来自解码器:解码器)抛出{
var container=try decoder.unkeydcontainer()
如果container.count!=nil{
let value=try container.decode([ArtistBio].self)
self=.multiple(值)
}否则{
let value=try container.decode(ArtistBio.self)
self=.single(值)
}
}
func encode(到编码器:编码器)抛出{
var container=encoder.unkeydcontainer()
切换自身{
案例。单身(让artistBio):
试试container.encode(artistBio)
案例。多个(让artistBios):
尝试container.encode(artistBios)
}
}
}
struct ArtistBio:可编码{
变量名称:String
var url:String
}
让jsonStrArray=“”
{
“艺人简介”:[
{
“url”:“url到pdf1”,
“姓名”:“艺术家姓名1”
},
{
“url”:“url到pdf2”,
“姓名”:“艺术家姓名2”
}
]
}
"""
让jsonStrSingle=“”
{
“艺人简介”:{
“url”:“url到pdf1”,
“姓名”:“艺术家姓名”
}
}
"""
做{
let show=尝试JSONDecoder().decode(show.self,from:jsonStrArray.data(使用:.utf8)!)
打印(“显示”,显示)
}捕捉(让错误){
打印(“解码多个错误”,错误)
}
做{
let show=try JSONDecoder().decode(show.self,from:jsonStrSingle.data(使用:.utf8)!)
打印(“显示”,显示)
}捕捉(让错误){
打印(“解码单个错误”,错误)
}
我不知道如何正确解码我的枚举对象。对于输入JSON的单版本和阵列版本,我都会遇到以下错误:
typeMismatch(Swift.Array<Any>,
Swift.DecodingError.Context(codingPath: [
CodingKeys(stringValue: "artistBio", intValue: nil),
_JSONKey(stringValue: "Index 0", intValue: 0)],
debugDescription:
"Expected to decode Array<Any> but found a dictionary instead.",
underlyingError: nil))
类型不匹配(Swift.Array,
Swift.DecodingError.Context(编码路径:[
编码键(stringValue:“artistBio”,intValue:无),
_JSONKey(stringValue:“索引0”,intValue:0)],
调试说明:
“应解码数组,但找到了字典。”,
参考误差:零)
您必须使用单值容器,而不是unkeydcontainer
,后者总是需要一个数组
enum ArtistBios: Codable {
case single(ArtistBio)
case multiple([ArtistBio])
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
let value = try container.decode([ArtistBio].self)
self = .multiple(value)
} catch DecodingError.typeMismatch {
let value = try container.decode(ArtistBio.self)
self = .single(value)
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .single(let artistBio):
try container.encode(artistBio)
case .multiple(let artistBios):
try container.encode(artistBios)
}
}
}
解码时请使用singleValueContainer
,然后尝试
解码成[ArtistBio].self
,如果出错,请先解码成ArtistBio.self
是,谢谢。我有点误会,因为文档中说可以使用singleValueContainer
对单个原语
值进行解码。我猜在这种情况下对象是基本的:)我建议做一个更有针对性的catch DecodingError.typemissmatch{..}
,让其他错误(keyNotFound,dataCorrupted)在第一时间传播try@NewDev接得好,谢谢。谢谢@vadian它能用!