Answer the question
In order to leave comments, you need to log in
How to make a structure filter?
Hello.
I receive here such array of the data.
[
{
"idSite": 204233,
"status": 0,
"Name": "",
"timeOfStatus": null
},
{
"idSite": 204234,
"status": 0,
"Name": "",
"timeOfStatus": null
},
{
"idSite": 204235,
"status": 0,
"Name": "",
"timeOfStatus": null
},
{
"idSite": 204236,
"status": 1,
"Name": "OK",
"timeOfStatus": "2019-06-26 12:58:16"
}
]
self.Obj = try JSONDecoder().decode([StatusObjects].self, from: data)
struct StatusObjects: Decodable {
let idSite: Int?
let status: Int?
let Name: String?
let timeOfStatus: String?
func convertToDictionary() -> Any {
return ["idSite": idSite!, "status": status!, "Name": Name!,"timeOfStatus": timeOfStatus!]
}
}
"status": 1
Answer the question
In order to leave comments, you need to log in
I'll show you two options.
-------------------------------------------------- ------
A simple variant (aka Dummi):
Normal filtering, after the memory has already been allocated. Simple, but memory spread and speed are lower.
-------------------------------------------------- ------ Advanced
variant :
Correcting the name of the properties.
Let's convert the dates to the appropriate format.
We carry out our custom encoding, tracking the status and throwing out an error so as not to allocate memory in vain.
import Foundation
let json = """
[{
"idSite": 204233,
"status": 0,
"Name": "",
"timeOfStatus": null
},
{
"idSite": 204234,
"status": 0,
"Name": "",
"timeOfStatus": null
},
{
"idSite": 204235,
"status": 0,
"Name": "",
"timeOfStatus": null
},
{
"idSite": 204236,
"status": 1,
"Name": "OK",
"timeOfStatus": "2019-06-26 12:58:16"
}]
"""
struct SomeStruct: Decodable {
let idSite: Int
let status: Bool
let name: String
let timeOfStatus: Date?
// Преобразуем Name -> name
private enum CodingKeys: String, CodingKey {
case idSite
case status
case name = "Name"
case timeOfStatus
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.idSite = try container.decode(Int.self, forKey: .idSite)
// Выбрасываем ошибку, если статус не равен 1. Не выделяем зря память.
let status = try container.decode(Int.self, forKey: .status)
if status == 1 {
self.status = true
} else {
throw DecodingError.dataCorruptedError(forKey: .status, in: container, debugDescription: "Status mast be `1`")
}
self.name = try container.decode(String.self, forKey: .name)
// Преобразуем строку с датой в объект для работы с датами Date
let date = try? container.decode(String.self, forKey: .timeOfStatus)
let dateFormatter: DateFormatter = {
$0.dateFormat = "yyyy-MM-dd HH:mm:ss"
$0.calendar = Calendar(identifier: .iso8601)
$0.timeZone = TimeZone(secondsFromGMT: 0)
$0.locale = Locale(identifier: "en_US_POSIX")
return $0
}(DateFormatter())
self.timeOfStatus = date != nil ? dateFormatter.date(from: date!) : nil
}
}
// Тип обёртка, которая даст легко отфильтровать данные, от тех, которые не прошли из-за статуса.
enum Throwable<T: Decodable>: Decodable {
case success(T), failure(Error)
init(from decoder: Decoder) throws {
do {
let decoded = try T(from: decoder)
self = .success(decoded)
} catch let error {
self = .failure(error)
}
}
var value: T? {
switch self {
case .failure(_):
return nil
case .success(let value):
return value
}
}
}
let decoder = JSONDecoder()
let arrayOfSomeStructs = try! decoder.decode([Throwable<SomeStruct>].self, from: json.data(using: .utf8)!)
let filteredArrayOfSomeStructs = arrayOfSomeStructs.compactMap{ $0.value }
print(filteredArrayOfSomeStructs.count)
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question