【问题标题】:Save complex JSON to Core Data in Swift在 Swift 中将复杂的 JSON 保存到 Core Data
【发布时间】:2019-03-04 11:39:24
【问题描述】:

我想将 Web 服务中的 JSON 结果保存到 Core 数据中,以下是 JSON 解析的代码。

if let jsonResult = try JSONSerialization.jsonObject(with: JSONData!, options: [.mutableContainers]) as? [String: AnyObject]

如果我打印 jsonResult,下面是输出

["Code": 00, "Desc": success, "iinData": <__NSArrayM 0x1c02531a0>
{
  name = “AAA”;
  iin = 123456;
  isOn = 0;
},
{
  name = "Allahabad Bank";
  iin = 608112;
  isOn = 0;
},
)

我可以将 Code, Desc 插入到 Entity1 中,但是如何将 innData 插入到 Entity2 中。

Entity1 StructureEntity2 Structure

以下是将 JSON 结果插入核心数据的代码

func createEntity1From(dictionary: [String: AnyObject]) -> NSManagedObject? {
    let context = CoreDataStack.sharedInstance.persistentContainer.viewContext
    if let Entity1 = NSEntityDescription.insertNewObject(forEntityName: “ParamDownload”, into: context) as? ParamDownload {
        Entity1.Code= dictionary[“name”] as? String
        Entity1.desc = dictionary[“desc”] as? String
        return Entity1
    }
}

【问题讨论】:

  • 使用转换为数据? Nskeyedarchieve?
  • 你做了什么来将解析的 JSON 保存到 CoreData?您似乎只使用了JSONSerialization 进行解码,但没有将数据转换为您创建的 CoreData 格式。
  • 感谢您的回复。我更新了将数据插入 entity1 的代码。您能否解释一下如何将 innData 插入 Entity2。因为这是一对多的关系数据。

标签: ios json swift core-data


【解决方案1】:

使用Decodable 将 JSON 直接解码为 Core Data 非常容易

  • 首先创建CodingUserInfoKeyJSONDecoder 的扩展,以便能够传递托管对象上下文

    extension CodingUserInfoKey {
        static let context = CodingUserInfoKey(rawValue: "context")!
    }
    
    extension JSONDecoder {
        convenience init(context: NSManagedObjectContext) {
            self.init()
            self.userInfo[.context] = context
        }
    }
    
  • 在两个类中添加对 Decodable 的一致性

    class Name: NSManagedObject, Decodable {
    
    class ParamDownload: NSManagedObject, Decodable {
    
  • 在类Name(不是扩展名)中添加

    private enum CodingKeys: String, CodingKey { case name, iin, isOn }
    
    required convenience init(from decoder: Decoder) throws {
        guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("NSManagedObjectContext is missing") }
        let entity = NSEntityDescription.entity(forEntityName: "Name", in: context)!
        self.init(entity: entity, insertInto: context)
        let values = try decoder.container(keyedBy: CodingKeys.self)
        name = try values.decode(String.self, forKey: .name)
        iin = try values.decode(String.self.self, forKey: .iin)
        isOn = try values.decode(Bool.self.self, forKey: .isOn)
    }
    
  • ParamDownload类(不是扩展名)中添加

    private enum CodingKeys: String, CodingKey { case code = "Code", desc = "Desc", names = "iinData" }
    
    required convenience init(from decoder: Decoder) throws {
        guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("NSManagedObjectContext is missing") }
        let entity = NSEntityDescription.entity(forEntityName: "ParamDownload", in: context)!
        self.init(entity: entity, insertInto: context)
        let values = try decoder.container(keyedBy: CodingKeys.self)
        code = try values.decode(String.self, forKey: .code)
        desc = try values.decode(String.self, forKey: .desc)
        names = try values.decode(Set<Name>.self, forKey: .names)
        names.forEach { $0.pd = self }
    }
    

要解码 JSON,请使用便捷初始化器创建解码器

let decoder = JSONDecoder(context: CoreDataStack.sharedInstance.persistentContainer.viewContext)

init 方法处理关系。

我建议尽可能多地声明可选的核心数据属性。
如果一个属性必须是可选的,请将decode 替换为decodeIfPresent

【讨论】:

  • 感谢您的回复。它工作正常,有一些变化。
  • 谢谢,很好的解决方案
【解决方案2】:

这对我也很有效,

private func createParamDownloadEntityFrom(dictionary: [String: AnyObject]) -> NSManagedObject? {
    let context = CoreDataStack.sharedInstance.persistentContainer.viewContext

    if let paramEntity = NSEntityDescription.insertNewObject(forEntityName: “ParamDwonload”, into: context) as? ParamDownload {
        paramEntity.code = dictionary[“code”] as? String
        paramEntity.desc = dictionary[“desc”] as? String
        let innData = dictionary["iinData"] as! NSArray


        for i in 0..<(innData.count-1) {

            if let nameEntity = NSEntityDescription.insertNewObject(forEntityName: Name
                , into: context) as? Name {

                if let val = innData[i] as? [String: Any] {
                    nameEntity.bankName = val[“name"] as? String
                    nameEntity.iin = val[“iin"] as? String
                    if let isOn = Int16(val[“isOn"] as! String) {
                        nameEntity.isOnus = isOn
                    }
                    paramEntity.addToNames(nameEntity)
                }

            }
        }
        return paramEntity
    }

【讨论】:

    【解决方案3】:

    我通过将 JSON 转换为数据来保存 JSON,并将该数据保存在 CoreData 中

    以下代码对我有用......

    func saveSpotsLocation(model: SpotsModel, packageId: String, regionName: String) {
      let newUser = NSEntityDescription.insertNewObject(forEntityName: "SpotsDetail", into: context)
      do {
        let data = NSKeyedArchiver.archivedData(withRootObject: model.dictionaryRepresentation())
        newUser.setValue(data, forKey: "data")
        newUser.setValue(packageId, forKey: "packageId")
        newUser.setValue(regionName, forKey: "regionName")
        try context.save()
      } catch {
        print("failure")
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多