从 JSON 响应中解析两个不同对象的数组

Posted

技术标签:

【中文标题】从 JSON 响应中解析两个不同对象的数组【英文标题】:parsing two different object's array from JSON response 【发布时间】:2018-04-24 12:39:11 【问题描述】:

我正在尝试解析 JSON 数据 .. 我知道如何为一个对象数组执行此操作 .. 但我不知道如何为具有两个不同对象数组的响应执行此操作 ..

例如这是 JSON:

  
"shifts": [
    
        "id": 4,
        "region": "Eastren",
        "city": "Khobar",
        "nationality": "1",
        "id_service": 2,
        "shift_date": "2018-04-05",
        "shift_type": "night",
        "weekday": "sunday",
        "quantity_staff": 8,
        "lead_hours": 2,
        "created_at": "2018-04-23 11:46:20",
        "updated_at": "2018-04-24 08:46:14",
        "deleted_at": null
    ,
    
        "id": 5,
        "region": "Eastren",
        "city": "Khobar",
        "nationality": "Phili",
        "id_service": 2,
        "shift_date": "2018-04-04",
        "shift_type": "night",
        "weekday": "sunday",
        "quantity_staff": 8,
        "lead_hours": 2,
        "created_at": "2018-04-23 11:47:25",
        "updated_at": "2018-04-23 12:53:05",
        "deleted_at": "2018-04-23"
    
],
"prices": [
    
        "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
    
]

它有两个对象数组..班次和价格..如何解析每个对象?

我的功能:

 func GetShiftsAndPrices(id: Int)

    let todosEndpoint: String = "my link"
    guard let todosURL = URL(string: todosEndpoint) else 
        print("Error: cannot create URL")
        return
    
    var todosUrlRequest = URLRequest(url: todosURL)
    todosUrlRequest.httpMethod = "POST"
    todosUrlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
    let newTodo: [String: Any] = ["id_service": id]
    let jsonTodo: Data
    do 
        jsonTodo = try JSONSerialization.data(withJSONObject: newTodo, options: [])
        todosUrlRequest.httpBody = jsonTodo
     catch 
        print("Error: cannot create JSON from todo")
        return
    

    let session = URLSession.shared

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

        // parse the result as JSON, since that's what the API provides
        do 

             //WHAT SHOULD I DO HERE?

                print("Success!")

         catch  
            print("error parsing response from POST")
            return
        
    
    task.resume()
   

我有班次和价格课程 .. 并且知道如何在单独响应时获得每个课程 .. 比如:

班次:

                  let decoder = JSONDecoder()
                decoder.keyDecodingStrategy = .convertFromSnakeCase
                let shifts1 = try decoder.decode([Shifts].self, from: responseData)
                var shifts = [Shift]()
                for shift in shifts1
                    let newshift = Shift(id: shift.id, region: shift.region, city: shift.city, nationality: shift.nationality, idService: shift.idService, shiftDate: shift.shiftDate, shiftType: shift.shiftType, weekday: shift.weekday, quantityStaff: shift.quantityStaff, leadHours: shift.leadHours)
                    shifts.append(newshift)
                


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

                let decoded  = userDefaults.object(forKey: "shifts") as! Data
                let decodedShift = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [Shift]

                for shift in decodedShift 
                    print(shift.id)
                

价格:

        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, idService: price.idService,nationality: price.nationality, price: price.price)
            print("2")
            prices.append(newprice)
            print(newprice.nationality)
        


        let 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)
        

如何在一个 JSON 响应中同时解析它们。我是新手。有人可以告诉我该怎么做吗?

【问题讨论】:

您可以创建一个容器对象,将班次和价格作为变量并制作 2 个映射,然后每个映射都将映射到它自己的类中 @ΒασίληςΔ。这该怎么做?对不起,我是这个 x_x 的新手 你没有两个数组;你有一本字典。所以这是一个可解码的结构。班次和价格是可解码的结构。这对于三个 Decodable 结构来说是微不足道的。根本不要使用 JSONSerialization。 @matt 那怎么办呢?你能举个例子吗? 【参考方案1】:

使用伞形结构

struct Root : Decodable 
    let shifts : [Shift]
    let prices : [Price]

还有两种不同的班次和价格结构:

struct Shift : Decodable 
    let id: Int
    let region, city, nationality : String
    let idService : Int
    let shiftDate, shiftType, weekday : String
    let quantityStaff, leadHours : Int
    let createdAt, updatedAt : String
    let deletedAt : String?


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


解码 JSON 写入

do 
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let result = try decoder .decode(Root.self, from: responseData)
    print(result.prices)
    print(result.shifts)
 catch  print(error) 

我还建议将shiftTypeweekday 等键直接解码为enum,例如

enum ShiftType : String, Decodable 
    case day, night


struct Shift : Decodable 
    let id: Int
    ...
    let shiftType : ShiftType
    ...

【讨论】:

【参考方案2】:
let shifts = responseJson.valueFor(key:"shifts") as? [String] ?? []
let prices = responseJson.valueFor(key:"prices") as? [String] ?? []
print("\(shifts) and \(prices)")

【讨论】:

什么是 responseJson? 是json解析后得到的响应 此帖子已被标记为低质量。 @SuganyaMarlin 请尝试解释 OP 在哪里遇到问题以及如何解决它,仅发布代码对寻求解释的更大社区没有帮助

以上是关于从 JSON 响应中解析两个不同对象的数组的主要内容,如果未能解决你的问题,请参考以下文章

如何解析具有相同键的不同数据类型的改造对象的json数组

快速解析动态键的json响应问题

从 Component 中的 Service 解析 JSON 数组对象

从改造响应中解析 JSON 对象

如何从android中的php关联数组解析JSON响应?

解析json数组响应/颤动