Анализ JSON с использованием декодируемого протокола - PullRequest
1 голос
/ 16 марта 2019

У меня есть json ниже, для которого я хочу разобрать / присвоить значения от

{
"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"
  }
 ]
}

Этот json имеет тип [Dictionary: Dictonary], который имеет только ключ "Rooms"

При создании структуры я должен создать

struct RoomsInfo: Decodable {
 let rooms: Rooms
}

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

Мой 1-й вопрос: поскольку у меня есть только ключ Rooms, есть ли возможность создать только одну структуру вместо двух?

Мой второй вопрос: что, если у моего json есть ключи "Rooms1", "Rooms2", "Rooms3", "Rooms4" ... в этом случае я могу создать структуру, которая подтверждает возможность декодирования, или мне нужно проанализировать это вручную?

Пожалуйста, совет

Ответы [ 2 ]

2 голосов
/ 16 марта 2019

Для первого вопроса у вас есть ключ с именем Room, поэтому он должен декодировать этот ключ, возможно ли не быть уверенным в этом, вместо того, чтобы анализировать, что JSON данные сначала вызывают значение этого ключа JSON["Rooms"], и анализируют то, что внутри, как [Room].self,

Для второго вопроса, если количество не ограничено, как если бы вы не знали, сколько будет Room количество ключей, тогда возможности Decoder ограничены, однако вы всегда можете отобразить значения как Dictionary, а затем декодировать значения как Room, не заботясь о ключе, этот трюк подойдет, но вы откажетесь от исходного Key.

Обновление для второго случая: Проверьте этот код ниже.

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 {

}
0 голосов
/ 16 марта 2019

Ответ # 1: Да, это возможно с nestedContainers, но это больше, чем выгода.

Ответ # 2: Расшифруйте словарь как [String:Room] или используйте пользовательские ключи кодирования, описанные в этот ответ

...