无法将 JSON 对象映射到领域

Posted

技术标签:

【中文标题】无法将 JSON 对象映射到领域【英文标题】:Cannot map JSON objects to Realm 【发布时间】:2016-05-17 09:16:00 【问题描述】:

更新 2 我试图通过添加一个自动擦除脚本来处理迁移错误,但我被抛出一个错误

预期声明

更新 1

我尝试将(response: Response<Particulars, NSError>) 替换为(response: Response<AnyObject, NSError>),但在let realm = try! Realm() 收到此错误

致命错误:“试试!”表达式意外引发错误

这是我的 POST 请求:

import Foundation
import Alamofire
import SwiftyJSON
import RealmSwift
import ObjectMapper
import AlamofireObjectMapper


class Login 
init(userName: String, passWord: String) 
Data.sharedInstance.userName = userName
Data.sharedInstance.passWord = passWord

// call this method to login
func getRequest() 
Alamofire.request(.POST, Data.todoEndpoint, parameters: ["username": Data.sharedInstance.userName!, "password": Data.sharedInstance.passWord!])
    .responseJSON  (response: Response<AnyObject, NSError>) in
        if let result = response.result.value
        
            let value = JSON(result)
               let realm = try! Realm()
               do
                  try realm.write
                      realm.add(result as! Object, update: true)
                                 
                 
                 catch let err as NSError 
                        print("Error with realm: " + err.localizedDescription)
                                            
        
        else
        
            print("JSON data is nil.")
        

 
 
 

旧帖

我有一个如下 JSON 响应,我可以通过使用 Alamofire 的发布请求获得它。我现在想使用 AlamofireObjectMapper 将我的数据映射到 Realm 中的数据库,但我被抛出了这个错误

无法将 '(Response)->()' 类型的值转换为预期值 参数类型“响应->无效”


 "name" : "Jonny Walker",
 "api_token" : "qwertyuiop1234567890",
 "profile_picture" : "http:default_profile_picture.jpg",
 "id" : 10,
 "email" : "jwalker@gmail.com"
 "username" : "jonny"

我该如何解决这个问题?

这是我的 POST 请求

Alamofire.request(.POST, Data.todoEndpoint, parameters: ["username": Data.sharedInstance.userName!, "password": Data.sharedInstance.passWord!])
.responseJSON  (response: Response<Particulars, NSError>) in
  var errorFound = Bool()
  var errorMessage = String()
  if let result = response.result.value
  
    let value = JSON(result)
    let realm = try! Realm()
    try! realm.write 
      for particular in result 
        realm.add(particular,update: true)
      
    
  

这是我初始化 Realm 对象的地方

class Particulars: Object, Mappable 
  dynamic var name = ""
  dynamic var email = ""
  dynamic var id = 0
  dynamic var profilePicture = ""
  dynamic var username = ""
  dynamic var apiToken = ""
  override static func primaryKey() -> String? 
    return "id"
  
  //Impl. of Mappable protocol
  required convenience init?(_ map: Map) 
    self.init()
  
  func mapping(map: Map) 
    id    <- map["id"]
    name <- map["name"]
    email <- map["email"]
    profilePicture <- map["profile_picture"]
    username <- map["username"]
    apiToken <- map["api_token"]
    

【问题讨论】:

【参考方案1】:

关于您问题的第二部分,关于迁移错误。您收到错误是因为您更改了对象定义,并且它们不再与 Realm 数据库中存储的内容匹配。您将需要处理从一个版本到下一个版本的干净迁移。或者,如果您的数据只是缓存的服务器数据,并且不需要为用户保留,因为它可以重新创建,(或者您处于调试/测试模式),您可以将其添加到您的 AppDelegate(在在你对 Realm 做任何事情之前,didFinishLaunchingWithOptions... 的顶部):

    // Auto wipe Realm store if schema has changed
    do 
        let _ = try Realm()
    
    catch 
        DataController.deleteRealmFilesAtPath(Realm.Configuration.defaultConfiguration.fileURL!)
    

然后,在您的 DataController 类中,包含此 static 方法:

static func deleteRealmFilesAtPath(fileURL: NSURL) 
    guard let path = fileURL.path else  return 
    let fileManager = NSFileManager.defaultManager()
    guard fileManager.fileExistsAtPath(path) else  return 

    do 
        try fileManager.removeItemAtPath(path)
        try fileManager.removeItemAtPath(path + ".lock")
        try fileManager.removeItemAtPath(path + ".note")
    
    catch 
        print("Unable to delete Realm files: \(error)")
    

如果架构已更改,这将在应用启动时擦除旧的数据库文件。当然,您也会丢失其中的任何数据,因此您只能在某些情况下使用它。

【讨论】:

嗨@Dave 我似乎无法将 do catch 添加到我的 AppDelegate。你知道我该如何解决吗?另外,当您提到 DataController 类时,您指的是我使用 realm.write 和 realm.add 的类吗? (查看更新后的帖子) do/catch 在 AppDelegate 中应该没问题,只要确保它在您的 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -&gt; Bool 方法中即可。 DataController 可以是您用来对数据函数进行分组的任何类,如果您没有专用的数据类,它甚至可以是您的 AppDelegate。更新:看到你的更新,你需要将你的 do/catch 移到你有 // Override... 的方法中 我收到“无法将 '__NSCFDictionary' (0x10c127178) 类型的值转换为 'RealmSwift.Object' (0x10bc7f770)。”在我的让领域=尝试!领域()线。你知道我该如何解决吗? 当然,这是我的代码 codeshare.io/xkjul(第 66-81 行)的链接以及我映射数据的代码 codeshare.io/1oQw9 好的,首先,从 try 中删除 !(第 69 行)。它在do 闭包内,因此如果失败,它将由catch 闭包处理。接下来,避免在任何地方使用!。尽量不要使用它。转换您的代码以检查类型,即as? Object。例如,在将其提供给 realm.add 之前进行检查。看起来 user 实际上是 Dictionary,而不是 Object,因此您的崩溃。【参考方案2】:

正如错误消息所说,您的完成块需要采用Response&lt;AnyObject, NSError&gt;,而不是Response&lt;Particulars, NSError&gt;

【讨论】:

如果我将 Particulars 替换为 AnyObject,我如何能够将 Particulars 类与我的 POST 请求相关联?【参考方案3】:

为了响应您的更新,当您对 Realm 进行更改时,您需要卸载该应用并重新安装。这应该可以消除您的迁移错误。

【讨论】:

以上是关于无法将 JSON 对象映射到领域的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AlamofireObjectMapper 将 JSON 字典添加到领域

如何在 Swift 中使用 Mappable 协议映射自定义对象的领域列表

领域 + 对象映射器 + SwityJSON

实现DDD领域驱动设计: Part 4

类模型-领域类映射

将数据插入领域数据库并取得进展?