Save complex JSON to Core Data in Swift

前端 未结 3 1046
名媛妹妹
名媛妹妹 2020-12-20 10:16

I want to save the JSON Result from web service to Core data, following is the code for JSON parsing.

if let jsonResult = try JSONSerialization.jsonObject(wi         


        
相关标签:
3条回答
  • 2020-12-20 10:17

    It's quite easy to decode the JSON directly into Core Data with Decodable

    • First of all create extensions of CodingUserInfoKey and JSONDecoder to be able to pass the managed object context

      extension CodingUserInfoKey {
          static let context = CodingUserInfoKey(rawValue: "context")!
      }
      
      extension JSONDecoder {
          convenience init(context: NSManagedObjectContext) {
              self.init()
              self.userInfo[.context] = context
          }
      }
      
    • Add conformance to Decodable in both classes

      class Name: NSManagedObject, Decodable {
      
      class ParamDownload: NSManagedObject, Decodable {
      
    • In the class Name (not the extension) add

      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)
      }
      
    • In the class ParamDownload (not the extension) add

      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 }
      }
      

    To decode the JSON create the Decoder with the convenience initializer

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

    the init methods handle the relationships.

    I recommend to declare the Core Data attributes as much non-optional as possible.
    If an attribute must be remain optional replace decode with decodeIfPresent.

    0 讨论(0)
  • 2020-12-20 10:28

    This also worked fine for me,

    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
        }
    
    0 讨论(0)
  • 2020-12-20 10:43

    I save JSON by converting it in into Data and save that Data in CoreData

    Following Code works for me......

    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")
      }
    }
    
    0 讨论(0)
提交回复
热议问题