【问题标题】:can a JSON be deserialized into an existing object?可以将 JSON 反序列化为现有对象吗?
【发布时间】:2022-01-20 02:43:45
【问题描述】:

我们有一些符合可编码接口的类。

现在我们有一个类似于深拷贝的需求,但我们需要将值传递到现有对象中。

例如:

class A: Codable{
    var a1: Int
    var a2: String
    ....aN: Codable
    enum CodingKeys: String, CodingKey {
        case a1
        case a2
        case a3
        ...
        case aN
    }
}
let a = A()

我们得到一个新的JSON,我们可以很容易的通过decode把它转换成A对象。

但是现在我们不想改变 a 的内存地址。我们希望其 ARC 保持当前状态。

也就是在反序列化的时候,我们想把内容直接写到对象a中。

我们希望更加自动化。我们可以根据allkeys遍历处理。我们不必逐个写。

a[keyPath: \.a1] = newObj[keyPath: \.a1]
a[keyPath: \.a2] = newObj[keyPath: \.a2]
...
a[keyPath: \.aN] = newObj[keyPath: \.aN]

or

a.a1 = newObj.a1
a.a2 = newObj.a2
...
a.aN = newObj.aN

【问题讨论】:

  • 一种选择是将 A 包装在另一个类中,并具有解码数据并替换 A 属性的函数。不确定这是否是一个合适的解决方案。

标签: ios swift


【解决方案1】:

反序列化总是会导致创建一个新对象。所以,我想,最可行(如果不是唯一)的选择是手动比较所有属性并相应地更新现有对象。

为方便起见,您可以在现有类中编写辅助方法。大概是这样的:

import Foundation

class A: Codable {
  var a1: String
  init(a1: String) {
    self.a1 = a1
  }
}

extension A {
  func updateWith(_ another: A) {
    if a1 != another.a1 {
      a1 = another.a1
    }
  }
}

let a = A(a1: "a1")

let anotherString = "{\"a1\":\"new a1\"}"
if let anotherData = anotherString.data(using: .utf8),
   let another = try? JSONDecoder().decode(A.self, from: anotherData) {
  a.updateWith(another)
}

print(a.a1) // "new a1"

【讨论】:

    猜你喜欢
    • 2012-09-13
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    相关资源
    最近更新 更多