如何使用具有数组的 2 个结构解码 JSON
Posted
技术标签:
【中文标题】如何使用具有数组的 2 个结构解码 JSON【英文标题】:How to decode a JSON with 2 structs that has an array 【发布时间】:2019-08-09 06:25:32 【问题描述】:我正在尝试解码 JSON 响应,但收到一条错误消息:
由于格式不正确,无法读取数据
响应位于["Product"]
节点中的数组中。我收到了回复,但我认为 ["PictureCollection"]
中的节点由于格式不正确而未正确解码。
这是 API 响应。一些 API 对象还不需要。只有我包含在 Product.swift 模型中的属性。
"RMessage" : "OK",
"RSuccess" : true,
"RValue" : null,
"InputKeyword" : “Soap”,
"ProductSearchMode" : 4,
"Product" : [
"MinPrice" : 2000,
"Gname" : “Soap Brand 1”,
"MaxPrice" : 3190,
"IconFlgList" : [
],
"SoldoutFlg" : null,
"PictureCollection" :
"Count" : 1,
"URL" : [
"https:someURL.jpg"
]
,
"ProgramBroadcastDate" : null,
"ID" : 107,
"Icon2OffValue" : “555”,
"Gcode" : “3333”
,
"Gcode" : “3334”,
"IconFlgList" : [
],
"PictureCollection" :
"Count" : 1,
"URL" : [
"https:https:someURL1.jpg"
]
,
"MaxPrice" : 2100,
"SoldoutFlg" : null,
"Icon2OffValue" : “551”,
"ProgramBroadcastDate" : null,
"ID" : 108,
"MinPrice" : 2001,
"Gname" : "Soap Brand 2”
这是我的代码:
struct Product: Codable
var id : Int!
var gcode : String!
var gname : String!
var minPrice : Int!
var maxPrice : Int!
var pictureCollection : PictureCollection
enum CodingKeys : String, CodingKey
case id = "ID"
case gcode = "GCode"
case gname = "Gname"
case minPrice = "MinPrice"
case maxPrice = "MaxPrice"
case pictureCollection = "PictureCollection"
struct PictureCollection : Codable
var Count : Int!
var URL : String!
var product : Product!
var productArray = [Product]()
let jsonResult = JSON(data)
for json in jsonResult["Product"].arrayValue
let jsonData = try json.rawData()
self.product = try JSONDecoder().decode(Product.self, from: jsonData)
self.productArray.append(self.product)
【问题讨论】:
你的问题很混乱。请花更多时间准备您的问题。没有名为picture
的元素。不清楚您要解码什么。
你不应该try
这样的方法。抓住DecodingError
。它会准确地告诉你哪里出了问题。
@Desdenova 对不起,我把你弄糊涂了。底部有一个 catch 块,错误为“无法读取数据,因为它的格式不正确”
确保像print(error)
这样打印错误对象以获取完整的错误消息
发布一个有效的json,我会尽力帮助你。
【参考方案1】:
问题在于struct PictureCollection
。
struct PictureCollection : Codable
var count : Int!
var url : String!
在您提供的 JSON 中,URL
是 array
的 String
。但在模型PictureCollection
中,您使用的是URL
类型的String
。
所以,你的struct PictureCollection
应该是,
struct PictureCollection : Codable
var count : Int
var url : [String]
而且,这里没有必要使用强制解包类型 (!
)。避免不必要地使用它们。可能会导致运行时异常。
另外,将您对decode(_:from:)
的调用嵌入到do-catch
块中,并在catch
块中打印整个error
对象,以找出问题的确切原因,即
do
//decode the JSON here...
catch
print(error)
【讨论】:
你好。你的回答对我来说是正确的,但我认为你的意思是这样吗? struct PictureCollection : Codable var Count : Int!变量网址:[字符串] @dreiohc 对。那只是复制粘贴错误。 我想到了这个,但没有尝试。我认为这太简单了。我会记下力展开的。感谢您的帮助。 您无法读取这样的JSONDecoder
错误。您需要抓住 DecodingError
并阅读其上下文的 debugDescription
和 codingPath
以了解实际错误。
@Desdenova 尝试打印错误,它将提供问题所在的所有详细信息。【参考方案2】:
我在下面添加代码请使用这个:
class Welcome: Codable
let rMessage: String
let rSuccess: Bool
let rValue:Int?
let inputKeyword: String
let productSearchMode: Int
let product: [Product]
enum CodingKeys: String, CodingKey
case rMessage = "RMessage"
case rSuccess = "RSuccess"
case rValue = "RValue"
case inputKeyword = "InputKeyword"
case productSearchMode = "ProductSearchMode"
case product = "Product"
init(rMessage: String, rSuccess: Bool, rValue: JSONNull?, inputKeyword: String, productSearchMode: Int, product: [Product])
self.rMessage = rMessage
self.rSuccess = rSuccess
self.rValue = rValue
self.inputKeyword = inputKeyword
self.productSearchMode = productSearchMode
self.product = product
// MARK: - 产品
class Product: Codable
let minPrice: Int
let gname: String
let maxPrice: Int
let iconFlgList: [String]
let soldoutFlg:bool?
let pictureCollection: PictureCollection
let programBroadcastDate:String?
let id: Int
let icon2OffValue, gcode: String
enum CodingKeys: String, CodingKey
case minPrice = "MinPrice"
case gname = "Gname"
case maxPrice = "MaxPrice"
case iconFlgList = "IconFlgList"
case soldoutFlg = "SoldoutFlg"
case pictureCollection = "PictureCollection"
case programBroadcastDate = "ProgramBroadcastDate"
case id = "ID"
case icon2OffValue = "Icon2OffValue"
case gcode = "Gcode"
init(minPrice: Int, gname: String, maxPrice: Int, iconFlgList: [JSONAny], soldoutFlg: JSONNull?, pictureCollection: PictureCollection, programBroadcastDate: JSONNull?, id: Int, icon2OffValue: String, gcode: String)
self.minPrice = minPrice
self.gname = gname
self.maxPrice = maxPrice
self.iconFlgList = iconFlgList
self.soldoutFlg = soldoutFlg
self.pictureCollection = pictureCollection
self.programBroadcastDate = programBroadcastDate
self.id = id
self.icon2OffValue = icon2OffValue
self.gcode = gcode
// MARK: - 图片集
class PictureCollection: Codable
let count: Int
let url: [String]
enum CodingKeys: String, CodingKey
case count = "Count"
case url = "URL"
init(count: Int, url: [String])
self.count = count
self.url = url
【讨论】:
不要将引用类型用作可编码的,除非它是您稍后需要改变的表单对象。这也不能以任何方式回答问题。 为什么要在结构体中添加 OP 不感兴趣的字段? 根据类名猜测 Welcome,我猜 nimesh 使用 app.quicktype.io 生成代码以上是关于如何使用具有数组的 2 个结构解码 JSON的主要内容,如果未能解决你的问题,请参考以下文章