Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何使用Swift JSONDecoder解码可以是数组或单个对象的JSON属性?_Ios_Json_Swift - Fatal编程技术网

Ios 如何使用Swift JSONDecoder解码可以是数组或单个对象的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

我试图解码JSON对象,其中一个属性可以是数组或单个对象。我的想法是引入带有
单个
多个
案例的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它能用!