繁体   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