我知道其他问题已经涵盖了这个问题,但是我已经跟着他们了,我仍然感到难过。这是我的JSON结构:
{
"FindBoatResult": {
"num_boats": 10,
"boat": [
{
"num_segments": 1,
"segments": [
{
"ident": "String",
"origin" : {
"code" : "String"
},
},
]
}
等等......但那就像结构一样深。 "段"有多个回报。在每个JSON响应中。在Swift中我有这个代码。
struct Result : Decodable {
let FindBoatResult : FindBoatResult
}
struct FindBoatResult : Decodable {
let boats : Boats
let num_boats : Int
}
struct Boats : Decodable {
let segments : [Segments]
}
struct Segments : Decodable {
let ident : String?
let origin : Origin
}
struct Origin : Decodable {
let code : String
}
func getBoats() {
let urlString = "http://myApi"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else {return}
let dataAsString = String(data: data, encoding: .utf8)
//print(dataAsString)
do {
let boats = try
JSONDecoder().decode(FindBoatResult.self, from: data)
print(boats)
} catch {
print(err)
}
}.resume()
}
这失败并抛出错误,但错误的打印为零。所以我无法告诉我错过了什么。 dataAsString按预期打印出JSON,所以我知道"数据"很好。
答案 0 :(得分:1)
我发现了一些小问题。尝试替换它:
struct FindBoatResult: Decodable {
let boats: Boats
let num_boats: Int
}
struct Boats: Decodable {
let segments: [Segments]
}
使用:
struct FindBoatResult: Decodable {
let boat: [Boat]
let num_boats: Int
}
struct Boat: Decodable {
let segments: [Segments]
}
最后,使用Result
类型(不是FindBoatResult
)进行解码:
JSONDecoder().decode(Result.self, from: data)
答案 1 :(得分:1)
扩展了Paulo的回答,我可能会进一步建议,如果您遇到JSON,其密钥不符合属性名称的Swift约定,那么您使用{{1模式将JSON键转换为更好的Swift属性名称,例如:
CodingKeys
因此,例如,当您表示一个对象数组时,使用复数(例如struct BoatResult: Decodable { // I'd simplify this name
let boatCollection: BoatCollection
enum CodingKeys: String, CodingKey {
case boatCollection = "FindBoatResult"
}
}
struct BoatCollection: Decodable { // I'd simplify this, too, removing "Find" from the name; verbs are for methods, not properties
let boats: [Boat]
let numberOfBoats: Int
enum CodingKeys: String, CodingKey {
case boats = "boat" // "boat" isn't great property name for an array of boats, so let's map the poor JSON key to better Swift name here
case numberOfBoats = "num_boats" // likewise, let's map the "_" name with better camelCase property name
}
}
struct Boat: Decodable { // This entity represents a single boat, so let's use "Boat", not "Boats"
let segments: [Segment]
}
struct Segment: Decodable { // This entity represents a single segment, so let's use "Segment", not "Segments"
let identifier: String
let origin: Origin
enum CodingKeys: String, CodingKey {
case identifier = "ident" // `ident` isn't a common name for identifier, so let's use something more logical
case origin
}
}
struct Origin: Decodable {
let code: String
}
),并使用boats
将误导性的CodingKeys
JSON键映射到这个名为boat
的数组引用更好。或者当你有一个像boats
这样的密钥时,不要觉得你必须在你的Swift属性中使用那个坏名字并使用更好的东西,如num_boats
(或numberOfBoats
或其他),并且失去了count
语法,这非常不合情理。
显然,如果你掌握了JSON的设计,你可以在那里修复一些选择不当的密钥名称,但即使你决定要让你的web服务使用{{1}语法,继续并使用_
来确保你的Swift对象符合camelCase约定。