Фильтрация пустых значений из API в swift

#ios #json #swift #api #uikit

Вопрос:

Я пытаюсь отфильтровать пустые и нулевые значения из api в формате json в swift(UIKit). Полные возвращаемые данные выглядят так, как показано ниже, но иногда могут содержать нулевые или пустые значения в characteristic ключе. Всегда будет одинаковое количество ключей.

 //Cat  { "breedname": "Persian", "picture": "https://catimage.random.png", "characteristic1": "Shy", "characteristic2": "Hungry all the time" "characteristic3": "Likes apples" "characteristic4": "Grey color" "characteristic5": "likes chin scratches"  }  { "breedname": "Bengal", "picture": "https://catimage.random.png", "characteristic1": "Active", "characteristic2": "Adventurous" "characteristic3": "" "characteristic4": "" "characteristic5": ""  }  { "breedname": "ragdoll", "picture": "https://catimage.random.png", "characteristic1": "Fiestey", "characteristic2": "sharp claws" "characteristic3": null "characteristic4": null "characteristic5": null  }   

Чтобы отфильтровать пустые и пустые значения перед отображением в пользовательском интерфейсе, у меня есть декодируемый класс, как показано ниже, и пользовательский класс инициализации с decodeifPresent методом, который изменяет значения null на nill. Однако для пустых значений я только что создал метод, который преобразует пустые строковые значения в ноль. Я не уверен, есть ли лучшие способы обработки пустых и пустых данных и их фильтрации? Я ссылаюсь на все декодируемые ключи в пользовательском интерфейсе, поэтому я не могу просто удалить сами ключи.

 struct Cat: Decodable {    let breedName: String  let picture: String  let characteristic1 : String?  let characteristic2 : String?  let characteristic3 : String?  let characteristic4 : String?  let characteristic5 : String?  enum CodingKeys: String, CodingKey {  case breedName  case picture  case characteristic1  case characteristic2  case characteristic3  case characteristic4  case characteristic5 }   func checkEmpty(s: String?) -gt; String? {  if s == "" {  return nil  }  return s  }  init(from decoder: Decoder) throws {  let container = try decoder.container(keyedBy: CodingKeys.self)   self.breedName= try container.decode(String.self, forKey: .breedName)  self.picture = try container.decode(String.self, forKey: .picture)  self.characteristic1 = try container.decodeIfPresent(String.self, forKey: .characteristic1)   self.characteristic2 = try container.decodeIfPresent(String.self, forKey: .characteristic2)  self.characteristic3 = try container.decodeIfPresent(String.self, forKey: .characteristic3)  self.characteristic4 = try container.decodeIfPresent(String.self, forKey: .characteristic4)  self.characteristic5 = try container.decodeIfPresent(String.self, forKey: .characteristic5)  self.characteristic1 = checkEmpty(s: self.characteristic1) self.characteristic2 = checkEmpty(s: self.characteristic2) self.characteristic3 = checkEmpty(s: self.characteristic3) self.characteristic4 = checkEmpty(s: self.characteristic4) self.characteristic5 = checkEmpty(s: self.characteristic5)  

Ответ №1:

Одним из решений является проверка пустоты в функции, определенной в расширении к строке

 extension String {  func emptyAsNil() -gt; String? {  self.isEmpty ? nil : self  } }  

Тогда вы могли бы сделать все за один шаг в init

 self.characteristic1 = try container.decodeIfPresent(String.self, forKey: .characteristic1)?.emptyAsNil()  

Но, возможно, лучшим решением будет собрать все эти свойства в коллекцию, такую как массив или словарь. Здесь я выбрал массив

 struct Cat: Decodable {  let breedName: String  let picture: String  var characteristics: [String] }  

а затем в инициализации мы добавляем в массив только ненулевые, непустые значения

 if let value = try container.decodeIfPresent(String.self, forKey: .characteristic1), !value.isEmpty {  characteristics.append(value) }  

или другой способ-перебирать клавиши

 let keys: [CodingKeys] = [.characteristic1,  .characteristic2,  .characteristic3,  .characteristic4,  .characteristic5]  for key in keys {  if let value = try container.decodeIfPresent(String.self, forKey: key), !value.isEmpty {  characteristics.append(value)  } }