在 Swift 中使用 swiftyJSON 成功将 JSON 写入 Realm DB

问题描述

我尝试从 JSON 文件(使用 swiftyJSON)写入 Realm DB 时出现以下错误

libc++abi.dylib:以 NSException 类型的未捕获异常终止 *** 由于未捕获的异常“RLMException”而终止应用程序,原因:“值无效”{ “车辆”:真的, “可见”:真实, “身份证”:0, “武器”:假, “流派”:“[幻想,一般]”, “名称”:“汽车” }' 来初始化类型为 'Item' 的对象:缺少键 'id''

我的 JSON 文件结构如下:

  [
  {
    "id": 0,"name": "Car","genres": "[Fantasy,General]","viewable": true,"weapon": false,"vehicle": true
  },{
    "id": 1,"name": "Truck","genres": "[General]",]

我的领域数据库类是:

class Item: Object {
    @objc dynamic var id: Int = 0
    @objc dynamic var name = ""
    let genres = List<String>()
    @objc dynamic var visable: Bool = false
    @objc dynamic var weapon: Bool = false
    @objc dynamic var vehicle: Bool = false
    
    override static func primaryKey() -> String? {
        return "id"
    }
    
    override static func indexedProperties() -> [String] {
        return ["genre","visable"]
    }
    
}

将JSON写入RealmDB的代码如下:

func jsonAdd() {

    if let path = Bundle.main.path(forResource: "Data",ofType: "json") {
        do {
            let data = try Data(contentsOf: URL(fileURLWithPath: path),options: .mappedIfSafe)
            let json = JSON(data)
            
            for (index,subJson):(String,JSON) in json {
                
                do {
                    try realm.write {
                        
                        realm.create(Item.self,value: subJson,update: .modified)
                        
                    }
                    
                } catch let error as NSError {
                    print("Unable to write")
                    print(error)
                }
                
            }
            
        } catch {
            print("Error")
        }
        
    }
}

我认为这个问题是一个 JSON 映射问题,但将 JSON 写入 Realm DB 包括流派作为列表的任何帮助将不胜感激。

注意:我已经设法在“写入”函数之前使用以下代码(基于 Realm 文档)写入 Realm DB,但似乎无法使其适用于我的 JSON 结构。

 let newdata = "{\"id\": 0,\"name\": \"Car\",\"genres\": [\"Fantasy\",\"General\"],\"viewable\": true,\"weapon\": false,\"vehicle\": true}".data(using: .utf8)!
    
 let json = try! JSONSerialization.jsonObject(with: newdata,options: [])

谢谢!

解决方法

通过以下方法解决:

  1. 我的 JSON 结构略有变化,如下所示:

     [
       {
         "id": 0,"name": "Car","genres": ["Fantasy","General"],"viewable": true,"weapon": false,"vehicle": true
       },{
         "id": 1,"name": "Truck","vehicle": true
       }
     ]
    
  2. 创建了一个新的流派对象以更好地处理列表

     class Genres: Object {
         @objc dynamic var id = 0
         @objc dynamic var name = ""
    
         override static func primaryKey() -> String? {
             return "id"
         }
     }
    
     class Item: Object {
         @objc dynamic var id = 0
         @objc dynamic var name = ""
         var genres = List<Genres>()
         @objc dynamic var viewable: Bool = false
         @objc dynamic var weapon: Bool = false
         @objc dynamic var vehicle: Bool = false
    
         override static func primaryKey() -> String? {
             return "id"
         }
    
         override static func indexedProperties() -> [String] {
             return ["genres","viewable"]
         }
    
     }
    

3) 至关重要的是,在 jsonADD 函数中更新了代码以创建一个新的项目对象,然后在尝试写入 Realm DB 之前将 JSON 值映射到该对象:

for (key,subJson):(String,JSON) in jsonObjects {
        
        let thisItem = Item()
        thisItem.id = subJson["id"].intValue
        thisItem.name = subJson["name"].stringValue
        thisItem.visable = subJson["viewable"].boolValue
        thisItem.weapon = subJson["weapon"].boolValue
        thisItem.vehicle = subJson["vehicle"].boolValue
        
        let genreArray = subJson["genres"].arrayValue
        
        for genre in genreArray {
            let string = genre.stringValue
            let predicate = NSPredicate(format: "name = %@",string)
            
            if let foundGenre = realm.objects(Genres.self).filter(predicate).first {
                thisItem.genres.append(foundGenre)
            }
        }
        
        do {
            try realm.write {
                realm.create(Item.self,value: thisItem,update: .modified)
            }
            
        } catch let error as NSError {
            print("Unable to write")
            print(error)
        }
    }