1

I have json below for which I want to parse/assign values from

{
"Rooms":[
  {
     "id":"100",
     "title":"CS Classroom",
     "description":"Classroom for Computer science students",
     "capacity":"50"
  },
  {
     "id":"101",
     "title":"Mechanical Lab",
     "description":"Mechanical Lab work",
     "capacity":"50"
  },
  {
     "id":"108",
     "title":"Computer Lab",
     "description":"Computer Lab work",
     "capacity":"50"
  }
 ]
}

This json is of type [Dictionary: Dictonary] which has only key "Rooms"

While creating struct should I create

struct RoomsInfo: Decodable {
 let rooms: Rooms
}

struct Rooms {
  let id: String
  let title: String
  let description: String
  let capacity: String
}

My 1st Question is: Since I have only Rooms key , Is there a possiblity to create just one struct instead of two ?

My 2nd Question is: What if my json has keys as "Rooms1", "Rooms2", "Rooms3", "Rooms4"... in this case can i create structure which confirms to decodable or do i need to parse it manually?

Please advice

Ashh
  • 569
  • 1
  • 6
  • 28

2 Answers2

2

For the first question, you have a key called Room so it has to decode that key, is it possible to not have it sure, instead of parsing that JSON data first call out the value of that key JSON["Rooms"], and parse what inside as a [Room].self ,

For the second question if the count is unlimited, as if you don't know how much Room key count are going to be, the Decoder abilities are limited then, however you can always map out the values as Dictionary and then decode the values as Room without caring about the key, this trick will do but you will abandon the original Key.

Update for the second case: Check out this code below.

typealias jsonDictionary = [String: Any]
let jsonData = json.data(using: .utf8)! // converting test json string to data
var arrayOfRooms: [Room] = []
do {
let serialized = try JSONSerialization.jsonObject(with: jsonData, options: []) // serializing jsonData to json object
    if let objects = serialized as? [String: Any] { //casting to dictionary
        for key in objects.keys { //looping into the keys rooms (n) number
           let rooms = objects[key] // getting those rooms by key
            let data = try JSONSerialization.data(withJSONObject: rooms!, options: []) //converting those objects to data again to parse
            var myRoom = try! JSONDecoder().decode([Room].self, from: data) // decoding each array of rooms
            arrayOfRooms.append(contentsOf: myRoom) // appending rooms to main rooms array declared on top
        print("Data", data) // just to check
        }
        print("MY Array Of Rooms Count \(arrayOfRooms.count)")
    } else {
        print("nil")
    }

} catch {

}
Mohmmad S
  • 5,001
  • 4
  • 18
  • 50
  • Thanks Mohmmad. I understood for 1st one.. like let response = try JSONDecoder().decode(Rooms.self, from: data[“Rooms”]) but for second one how can I omit key? because in .decode() function i need to pass from data..how can i pass that..can u pls let me know – Ashh Mar 16 '19 at 00:49
  • do you need an example of the second one ? – Mohmmad S Mar 16 '19 at 00:49
  • this is where we have key with rooms1, 2, 3 .. an unknown number of keys – Mohmmad S Mar 16 '19 at 01:23
0

Answer #1: Yes, it's possible with nestedContainers but the effort is greater than the benefit.

Answer #2: Decode the dictionary as [String:Room] or use custom coding keys described in this answer

vadian
  • 274,689
  • 30
  • 353
  • 361