解码 JSON 响应

Posted

技术标签:

【中文标题】解码 JSON 响应【英文标题】:Decode JSON response 【发布时间】:2018-04-24 07:10:58 【问题描述】:

我正在尝试从 JSON 响应中获取一些价格数据并将其保存在用户默认值中...

价格类别是:

  import Foundation

struct Prices : Decodable
let id, id_service: Int
let nationality: String
let price: Int
let createdAt: String?
let updatedAt: String?


class Price : NSObject, NSCoding 
var id, id_service: Int
var nationality: String
var price: Int
var createdAt: String?
var updatedAt: String?


init(id: Int, id_service: Int, nationality: String, price: Int) 
    self.id = id
    self.id_service = id_service
    self.nationality = nationality
    self.price = price



required convenience init(coder aDecoder: NSCoder) 
    let id = aDecoder.decodeInteger(forKey: "id")
    let id_service = aDecoder.decodeInteger(forKey: "id_service")
    let nationality = aDecoder.decodeObject(forKey: "nationality") as! String
    let price = aDecoder.decodeInteger(forKey: "price")
    self.init(id: id, id_service: id_service, nationality: nationality, price: price)


func encode(with aCoder: NSCoder) 
    aCoder.encode(id, forKey: "id")
    aCoder.encode(id_service, forKey: "id_service")
    aCoder.encode(nationality, forKey: "nationality")
    aCoder.encode(price, forKey: "price")



我调用的方法是:

   func GetPrices() 

let todoEndpoint: String = "my link"
guard let url = URL(string: todoEndpoint) else 
    print("Error: cannot create URL")
    return

let urlRequest = URLRequest(url: url)

let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)

let task = session.dataTask(with: urlRequest) 
    (data, response, error) in
    guard error == nil else 
        print("error calling GET on /public/api/services")
        print(error!)
        return
    
    guard let responseData = data else 
        print("Error: did not receive data")
        return
    
    do 

        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        let prices1 = try decoder.decode([Prices].self, from: responseData)
        print("1")
        var prices = [Price]()
        for price in prices1
            let newprice = Price(id: price.id, id_service: price.id_service,nationality: price.nationality, price: price.price)
            print("2")
            prices.append(newprice)
             print(newprice.nationality)
        


        var userDefaults = UserDefaults.standard
        let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: prices)
        userDefaults.set(encodedData, forKey: "prices")
        userDefaults.synchronize()

        let decoded  = userDefaults.object(forKey: "prices") as! Data
        let decodedPrice = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [Price]

        for price in decodedPrice 
            print(price.nationality)
        


     catch  
        print("error trying to convert data to JSON")
        return
    

task.resume()

我拥有的 JSON 是这样的(它现在只有一个.. 但它是一个数组):

[

    "id": 1,
    "id_service": 2,
    "nationality": "Phili",
    "price": 150,
    "created_at": "2018-04-23 11:43:40",
    "updated_at": "2018-04-23 11:43:40",
    "deleted_at": null

]

问题是我总是收到此消息:尝试将数据转换为 JSON 时出错

为什么?我做错了什么?如何解决?

【问题讨论】:

在你的catch块print(error.localizedDescription)中没有必要遍历price1并创建一个新数组,它已经是一个数组 @Scriptable 收到此错误:无法读取数据,因为它丢失了。 它不见了?尝试打印 data 或 data.count convertFromSnakeCase 选项将id_service 解码为idService 为什么要使用包含相同数据的类和结构?将 JSON 保存为 Data 中的 UserDefaults 并在读取时将其解码为结构体。 【参考方案1】:

您正在使用 .convertFromSnakeCase 进行解码,因此您的属性应该是驼峰式的。

decoder.keyDecodingStrategy = .convertFromSnakeCase

参考。 https://developer.apple.com/documentation/foundation/jsondecoder.keydecodingstrategy/2949105-convertfromsnakecase

所以要进行修复,请将您的属性名称 id_service 更改为 idService,如下所示。

struct Prices : Decodable
    let id, idService: Int
    let nationality: String
    let price: Int
    let createdAt: String?
    let updatedAt: String?

为了更好地理解,您也可以查看 .useDefaultKeys https://developer.apple.com/documentation/foundation/jsondecoder.keydecodingstrategy/2949131-usedefaultkeys

【讨论】:

非常感谢!

以上是关于解码 JSON 响应的主要内容,如果未能解决你的问题,请参考以下文章

无法解码 JSON 响应

对 GMSCoordinateBounds 数组的 Swift 解码 JSON 响应

如何使用 Codable 解码具有更改键的 json 响应?

用一个结构解码两个不同的 JSON 响应? [复制]

使用 Struct 解码 JSON 响应的 Alamofire 错误

如何解码 youtube api v3 json 响应