簡體   English   中英

從 Swift 中的 JSON 數組中解析有效對象

[英]Parse valid objects from JSON array in Swift

我有一個像這樣的可編碼結構

struct User: Codable {
    let id: String
    let registrationId: String
    let firstName: String?
    let lastName: String?
}

現在,來自服務器的響應包含一個這樣的數組

 [
  {
    "id": "1",
    "registrationId": "r1",
    "firstName": "Jon",
    "lastName": "Doe"
  },
  {
    "id": "2",
    "registrationId": null,
    "firstName": null,
    "lastName": null
  },
  {
    "id": "3",
    "registrationId": null,
    "firstName": null,
    "lastName": null
  },
  {
    "id": "4",
    "registrationId": "r4",
    "firstName": "Jon",
    "lastName": "Snow"
  }
]

我想將其解析為 [User] 但只有那些具有有效(非空) registrationId的人。 我知道如何在 swift 中解析 JSON。 但是這里的問題是由於中間的兩個無效數據,整個響應會遇到解碼錯誤。 但我想將它解析為一個包含有效對象的[User]數組(在這種情況下是第一個和最后一個對象)。

非常感謝任何提示或幫助。

1-將registrationId設為可選

 let registrationId: String?

2-

 let res = try JSONDecoder().decode([User].self,from:data)
 let filtered = res.filter { $0.registrationId != nil }

畢竟,這些數據必須來自數據庫或數組。 通過將id參數作為主鍵,registrationId參數作為外鍵,如果你正在處理registrationId參數,你可以創建一個生產序列,或者如果它在數組上,你可以鏈接生成的方法該registrationId的序列。

現在我知道如何實現這一目標了。

struct User: Codable {
    let id: String
    let registrationId: String
    let firstName: String?
    let lastName: String?
}

struct WrappedDecodableArray<Element: Decodable>: Decodable {
    let elements: [Element]

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        var elements = [Element]()
        while !container.isAtEnd {
            if let element = try? container.decode(Element.self) {
                elements.append(element)
            } else {
                // move the container currentIndex forward
                _ = try container.decode(Block.self)
            }
        }
        self.elements = elements
    }

    private struct Block: Decodable {}
}

func testUserParsing() {
    let jsonStr = """
    [
      {
        "id": "1",
        "registrationId": "r1",
        "firstName": "Jon",
        "lastName": "Doe"
      },
      {
        "id": "2",
        "registrationId": null,
        "firstName": null,
        "lastName": null
      },
      {
        "id": "3",
        "registrationId": null,
        "firstName": null,
        "lastName": null
      },
      {
        "id": "4",
        "registrationId": "r4",
        "firstName": "Jon",
        "lastName": "Snow"
      }
    ]
    """

    let jsonData = jsonStr.data(using: .utf8)!
    let wrappedArray = try! JSONDecoder().decode(WrappedDecodableArray<User>.self, from: jsonData)
    print(wrappedArray.elements)
}

如果我們可以在某些條件下(例如extension Array where Element == User )覆蓋 Array 的init(from decoder: Decoder)會更優雅。 但看起來這是不可能的。 擴展內的初始化程序不能覆蓋原來的初始化程序,因此永遠不會被調用。 所以現在看起來用結構包裝是唯一的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM