【问题标题】:how to parse JSON array in swift?如何快速解析 JSON 数组?
【发布时间】:2021-03-16 20:14:44
【问题描述】:

// 这是我从 Pokemon api 得到的响应

[
    null,
    {
        "attack": 49,
        "defense": 49,
        "description": "Bulbasaur can be seen napping in bright sunlight.\nThere is a seed on its back. By soaking up the sun’s rays,\nthe seed grows progressively larger.",
        "evolutionChain": [
            {
                "id": "2",
                "name": "ivysaur"
            },
            {
                "id": "3",
                "name": "venusaur"
            }
        ],
        "height": 7,
        "id": 1,
        "imageUrl": "https://firebasestorage.googleapis.com/v0/b/pokedex-bb36f.appspot.com/o/pokemon_images%2F2CF15848-AAF9-49C0-90E4-28DC78F60A78?alt=media&token=15ecd49b-89ff-46d6-be0f-1812c948e334",
        "name": "bulbasaur",
        "type": "poison",
        "weight": 69
    },
    {
        "attack": 62,
        "defense": 63,
        "defense:": 63,
        "description": "There is a bud on this Pokémon’s back. To support its weight,\nIvysaur’s legs and trunk grow thick and strong.\nIf it starts spending more time lying in the sunlight,\nit’s a sign that the bud will bloom into a large flower soon.",
        "evolutionChain": [
            {
                "id": "2",
                "name": "ivysaur"
            },
            {
                "id": "3",
                "name": "venusaur"
            }
        ]
]

//我要从响应中寻找的数据

struct APIData: Codable {
    let pokemon: String
    let type: String
    let description: String
    let attack: Int
    let height: Int
    let weight: Int
    let defence: Int
    let evolutionChain: EvolutionChain
}

struct EvolutionChain: Codable {
    let name : String
}

///我才刚刚开始,所以对网络工作了解不多

class ViewController: UIViewController {

//url with accesstoken
let myUrl =  "https://pokedex-bb36f.firebaseio.com/pokemon.json"

//fetchdata

func fetchdata(){
        
        guard let url = URL(string: myUrl) else { return }
        
        let task = URLSession.shared.dataTask(with: url) { (data, _, error) in
            guard let data = data, error == nil else {
                print("error")
                return
            }
            //we have the data now decode
            
            var result: APIData?
            
            do {
                result = try JSONDecoder().decode(APIData.self, from: data)
            } catch {
                print("data decoding failed")
            }
            
            guard let json = result else {
                return
            }
            
            print(json.description)

        }
        task.resume()
    }

    
    override func viewDidLoad() {
        super.viewDidLoad()
        fetchdata()
    }
}

/// 错误与支持

  1. 数据解码失败
  2. 谁能提供我在解码数组时遵循的正确结构

【问题讨论】:

  • 问题出在第一个null。您无法解码[APIData?].self。您可以声明一个包装结构,实现init(from: decoder 并解码unkeyedContainer 以过滤nil 条目。
  • ^^ 如果您只想导入某些字段,则需要使用 CodingKeys 来选择您想要的字段。如果您费心去搜索,这里有无数的 Codable 教程。
  • @flanker 这不是真的。如果结构成员名称和 JSON 键不同或排除结构中的计算属性或常量等对象,则需要 CodingKeys。
  • 是的,空值。谢谢!
  • 这能回答你的问题吗? How to create a struct to match this Json

标签: json swift


【解决方案1】:

您可能正在做正确的事情。问题在于 json 本身。它不是正确的 json 格式。所有 json 必须以 { } 开头。对于仅数组有效负载,您将拥有以下格式:

 {
   "values": []
 }

所以对于你的 json,后端应该以这种格式返回一些东西:

{"value": [
    {
        "attack": 49,
        "defense": 49,
        "description": "Bulbasaur can be seen napping in bright sunlight.\nThere is a seed on its back. By soaking up the sun’s rays,\nthe seed grows progressively larger.",
        "evolutionChain": [
            {
                "id": "2",
                "name": "ivysaur"
            },
            {
                "id": "3",
                "name": "venusaur"
            }
        ],
        "height": 7,
        "id": 1,
        "imageUrl": "https://firebasestorage.googleapis.com/v0/b/pokedex-bb36f.appspot.com/o/pokemon_images%2F2CF15848-AAF9-49C0-90E4-28DC78F60A78?alt=media&token=15ecd49b-89ff-46d6-be0f-1812c948e334",
        "name": "bulbasaur",
        "type": "poison",
        "weight": 69
    },
    {
        "attack": 62,
        "defense": 63,
        "defense:": 63,
        "description": "There is a bud on this Pokémon’s back. To support its weight,\nIvysaur’s legs and trunk grow thick and strong.\nIf it starts spending more time lying in the sunlight,\nit’s a sign that the bud will bloom into a large flower soon.",
        "evolutionChain": [
            {
                "id": "2",
                "name": "ivysaur"
            },
            {
                "id": "3",
                "name": "venusaur"
            }
        ]
    }
]}

Swift 模型应该是:

// MARK: - APIData
struct APIData: Codable {
    let value: [Value]
}

// MARK: - Value
struct Value: Codable {
    let attack, defense: Int
    let valueDescription: String
    let evolutionChain: [EvolutionChain]
    let height, id: Int?
    let imageURL: String?
    let name, type: String?
    let weight, valueDefense: Int?

    enum CodingKeys: String, CodingKey {
        case attack, defense
        case valueDescription = "description"
        case evolutionChain, height, id
        case imageURL = "imageUrl"
        case name, type, weight
        case valueDefense = "defense:"
    }
}

// MARK: - EvolutionChain
struct EvolutionChain: Codable {
    let id, name: String
}

【讨论】:

  • 所有 json 必须以 { } 开头。不,它不必。数组以[ 开头。关键是第一项是null
  • 我找到了解决方法,方法是从 json o/p 中删除空值。所以它起作用了,为什么我需要编码密钥??
  • 在您的情况下,编码键不是强制性的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-14
  • 1970-01-01
相关资源
最近更新 更多