【问题标题】:Swift 4 The data couldn’t be read because it isn’t in the correct formatSwift 4 无法读取数据,因为它的格式不正确
【发布时间】:2018-12-25 10:38:39
【问题描述】:

我正在开发一个项目来学习如何解析 JSON。我正在尝试将 JSON 解析为 struct。我正在尝试使用接下来的代码来执行此操作,但出现以下错误:

Err 由于格式不正确,无法读取数据。

我做错了什么?我也尝试使用 Alamofire,但没有找到将其解析为 struct 的方法。

func getData(){
    let gitUrl = URL(string: "http://95.46.99.250:9095/api/v1/institution-categories")
    URLSession.shared.dataTask(with: gitUrl!) { (data, response
        , error) in
        let data = data
        print(data)
        do {
            let decoder = JSONDecoder()
            let gitData = try decoder.decode([Root].self, from: data!)

        } catch let err {
            print("\nErr", err.localizedDescription)
        }
        }.resume()
}

结构

struct Root: Codable {
    let  data: [InnerItem]
}
struct InnerItem:Codable {
    let  id: Int?
    let  image: String?
    let  name: String?

    private enum CodingKeys : String, CodingKey {
        case id = "id", image = "image", name = "name"
    }
}

JSON

{
"data": [
    {
        "id": 1,
        "name": "Пабы и бары",
        "image": "http://95.46.99.250:9095/storage/photos/beer@2x.png"
    },
    {
        "id": 2,
        "name": "Кафе",
        "image": "http://95.46.99.250:9095/storage/photos/coffee@3x.png"
    },
    {
        "id": 3,
        "name": "Ночной клуб",
        "image": "http://95.46.99.250:9095/storage/photos/0201f7523bc2028f174710b51379e432.png"
    },
    {
        "id": 4,
        "name": "Ресторан",
        "image": "http://95.46.99.250:9095/storage/photos/restaurants@3x.png"
    },
    {
        "id": 5,
        "name": "Караоке-клуб",
        "image": "http://95.46.99.250:9095/storage/photos/microphone.png"
    },
    {
        "id": 6,
        "name": "Суши-бар",
        "image": "http://95.46.99.250:9095/storage/photos/sushi.png"
    },
    {
        "id": 7,
        "name": "Пиццерии",
        "image": "http://95.46.99.250:9095/storage/photos/pizza.png"
    },
    {
        "id": 8,
        "name": "Кальянная",
        "image": "http://95.46.99.250:9095/storage/photos/c111d1e5ad6b90b61ac36836d220ebba.png"
    },
    {
        "id": 9,
        "name": "Общая",
        "image": "http://95.46.99.250:9095/storage/photos/Group 315@3x.png"
    }
]
}

【问题讨论】:

  • [Root].selfRoot.self?您的 JSON 不是顶级数组。另外,不要使用localizedDescription,打印完整的错误,然后应该更明确。
  • ... 并且(尽管与问题无关)删除 InnerItem 中的冗余 CodingKeys 和所有问号,因为 JSON 字典清楚地始终包含所有键。 image 甚至可以解码为URL
  • 不要打印本地化描述,因为它没有上下文。打印错误以查看序列化失败的确切位置。

标签: ios json swift parsing


【解决方案1】:

试试这个

let gitData = try decoder.decode(Root.self, from: data!)

遍历您的数据

for singleData in gitData.data where (singleData.name ?? "") == "Cafe" {
    print(singleData.image)
}

【讨论】:

  • 所以我在我的结构中获取数据......现在,我如何从 InnerItem 获取数据。例如,如果 InnerItem.name == cafe GET InnerItem.image for this name
  • 这样我会得到所有的图像......我怎么能把它们和名字联系起来? if InnerItem.name == cafe GET InnerItem.image
  • 如果可以遍历,可以边走边加必要条件。我添加了一个将打印名称为“Cafe”的图像的 URL
【解决方案2】:

对我来说,“无法读取数据,因为它的格式不正确”的问题。与我尝试使用的特定 XLSX 文件有关。我在 Excel 中创建了一个新的 XLSX 文件,并将其添加到我的项目中,并且成功了!然后我只是将我需要的数据从给我错误的文件中粘贴到新创建的 XLSX 文件中并解析!

    static func load() {
    
    guard let filePath = Bundle.main.path(forResource: "test", ofType: "xlsx", inDirectory: nil) else {
        fatalError("XLSX file not exist")
    }
    
    let file = XLSXFile(filepath: filePath)
    
    do {
                   
        let parseBooks = try? file?.parseWorkbooks()
        
        for eachBook in parseBooks! {
            
            for (name, path) in try file!.parseWorksheetPathsAndNames(workbook: eachBook) {
    
                let worksheet = try file!.parseWorksheet(at: path)
                let sharedStrings = try file!.parseSharedStrings()
                print(sharedStrings)
    
            }
        }
    } catch {
        print("Error: \(error.localizedDescription)")
    }
  }

【讨论】:

  • 您的答案与问题无关,除了相同的无意义的通用错误消息。即使在您的情况下,也将 error.localizedDescription 替换为 error 以获得潜在的 real 错误。
【解决方案3】:

? 排查coding/decoding 错误

使用codables 时,不要打印.localizedDescription,而是尝试打印error 本身!所以编译器会准确描述问题出在哪里!

do {
    let decoder = JSONDecoder()
    let decoded = try decoder.decode([Root].self, from: data!)
} catch {
    // print(localizedDescription) // <- ⚠️ Don't use this!

    print(String(describing: error)) // <- ✅ Use this for debuging!
}

你的情况

它会指出:

  • 解码器尝试将根对象解码为Array,但找到了Dictionary

所以你关注这个问题并看到你应该替换:

decoder.decode([Root].self, from: data!)

与:

decoder.decode(Root.self, from: data!)

【讨论】:

  • print(String(describing: error)) //
  • 我使用相同但发现相同问题
猜你喜欢
  • 2019-07-28
  • 2021-11-11
  • 1970-01-01
  • 1970-01-01
  • 2017-06-12
  • 2020-03-11
  • 1970-01-01
  • 2016-10-15
相关资源
最近更新 更多