Reputation: 205
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(with: JSONData!, options: [.mutableContainers]) as? [String: AnyObject]
If i prints jsonResult, following is the output
["Code": 00, "Desc": success, "iinData": <__NSArrayM 0x1c02531a0>
{
name = “AAA”;
iin = 123456;
isOn = 0;
},
{
name = "Allahabad Bank";
iin = 608112;
isOn = 0;
},
)
I can able to insert Code, Desc into Entity1, but how to insert innData into Entity2 .
Entity1 Structure Entity2 Structure
Following is the code for inserting JSON result into core data
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
}
}
Upvotes: 4
Views: 9335
Reputation: 275
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")
}
}
Upvotes: 0
Reputation: 205
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
}
Upvotes: -1
Reputation: 285059
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
.
Upvotes: 9