【问题标题】:iOS - Map a root JSON array with ObjectMapper in swiftiOS - 在 swift 中使用 ObjectMapper 映射根 JSON 数组
【发布时间】:2015-11-27 22:54:00
【问题描述】:

我使用库 ObjectMapper 将 json 与我的对象映射,但我在映射根 json 数组时遇到了一些问题。

这是收到的json:

[
   {
       CustomerId = "A000015",
       ...
   },
   {
       CustomerId = "A000016",
       ...
   },
   {
       CustomerId = "A000017",
       ...
   }
]

这是我的对象

class Customer : Mappable
{
    var CustomerId : String? = nil

    class func newInstance(map: Map) -> Mappable? {
        return Customer()
    }

    func mapping(map: Map) {
        CustomerId   <- map["CustomerId"]
    }
}

我将控制器中的 json 映射为

let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as! NSArray

if (error != nil) {
    return completionHandler(nil, error)
} else {
    var customers = Mapper<Customer>().map(json)
}

但它不起作用,我尝试了Mapper&lt;[Customer]&gt;().map(json),但它也不起作用。 最后,我尝试创建一个包含 Customer 数组的新 swift 对象 CustomerList,但它不起作用。

您知道如何映射根数组的 json 吗?

谢谢。

【问题讨论】:

  • 如果我错了,请纠正我,但如果你收到一个数组,值不应该在 brackets 而不是 parentheses 内这个[ {CustomerId = "A000015" }, {...} ] ?
  • 是的,我认为是XCode中println的编码显示。当我使用 println 时,它会用括号和分号显示。但在 Postman 上,它带有括号和逗号。

标签: ios json swift nsarray


【解决方案1】:

我终于解决了我的问题:

控制器中的映射方法应该是

let json : AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error)

if (error != nil) {
    return completionHandler(nil, error)
} else {
    var customer = Mapper<Customer>().mapArray(json)! //Swift 2
    var customer = Mapper<Customer>().mapArray(JSONArray: json)! //Swift 3
}

如果它可以帮助某人。

【讨论】:

    【解决方案2】:

    JSONObjectWithData(::) 与正确的条件向下转换类型一起使用

    您的 JSON 类型为 [[String: AnyObject]]。因此,在 Swift 2 中,您可以使用 JSONObjectWithData(::)[[String: AnyObject]] 类型的条件向下转换,以防止使用 NSArrayAnyObject!

    do {
        if let jsonArray = try NSJSONSerialization
            .JSONObjectWithData(data, options: []) as? [[String: AnyObject]] {
            /* perform your ObjectMapper's mapping operation here */
        } else {
            /* ... */
        }
    }
    catch let error as NSError {
        print(error)
    }
    

    使用mapArray(:)方法映射到Customer

    ObjectMapperMapper 类提供了一个名为mapArray(:) 的方法,该方法具有以下声明:

    public func mapArray(JSONArray: [[String : AnyObject]]) -&gt; [N]?

    ObjectMapper 文档对此进行了说明:

    将 JSON 字典数组映射到 Mappable 对象数组

    因此,您的最终代码应如下所示:

    do {
        if let jsonArray = try NSJSONSerialization
            .JSONObjectWithData(data, options: []) as? [[String: AnyObject]] {
            let customerArray = Mapper<Customer>().mapArray(jsonArray)
            print(customerArray) // customerArray is of type [Customer]?
        } else {
            /* ... */
        }
    }
    catch let error as NSError {
        print(error)
    }
    

    使用map(:)方法映射到Customer

    ObjectMapperMapper 类提供了一个名为map(:) 的方法,该方法具有以下声明:

    func map(JSONDictionary: [String : AnyObject]) -&gt; N?

    ObjectMapper 文档对此进行了说明:

    将 JSON 字典映射到符合 Mappable 的对象

    作为前面代码的替代方案,以下代码显示了如何使用 map(:) 将 JSON 映射到 Customer

    do {
        if let jsonArray = try NSJSONSerialization
            .JSONObjectWithData(data, options: []) as? [[String: AnyObject]] {
            for element in jsonArray {
                let customer = Mapper<Customer>().map(element)
                print(customer) // customer is of type Customer?
            }
        } else {
            /* ... */
        }
    }
    catch let error as NSError {
        print(error)
    }
    

    【讨论】:

      【解决方案3】:

      解决根数组与泛型对象映射问题的一个好方法是创建一个泛型对象,该对象在类实现中创建一个包含对象的列表。让我们在下面看一个这种实现的例子:

          Alamofire.request(REQ_URL_STRING, 
             method: REQ_METHOD(eg.: .GET), 
             parameters: REQ_PARAMS, 
             encoding: REQ_ENCODING, 
             headers: REQ_HEADERS).responseObject { (response: DataResponse<GenericResponseList<SingleElement>>) in
                  //your code after serialization here
          }
      

      在上面的代码中,您将使用自己的值填充大写变量。检查闭包中的响应返回是否是来自 Alamofire 的通用对象 DataResponse,我确实创建了另一个名为 GenericResponseList 的对象。我在“”中放入了我将从服务器获取列表的对象的类型。在我的例子中,它是一个 SingleElements 列表。

      现在,看看下面的 GenericResponseList 的实现:

      final class GenericResponseList<T: Mappable>: Mappable {
      
          var result: [T]?
      
          required convenience init?(map: Map) {
              self.init()
          }
      
          func mapping(map: Map) {
              result <- map["result"]
          }
      }
      

      看一下,我在类中有一个变量,它是我发送给这个类的泛型类型的列表。

      var result: [T]?
      

      所以现在,当您获得 JSON 时,它会将其转换为 SingleElement 列表。

      希望对您有所帮助:)

      【讨论】:

      • 不适合我 ObjectMapper 无法序列化响应
      【解决方案4】:

      在我最近的 Swift 3 中的相同情况下,能够解决以 root 身份存在于 Array 中的对象映射器。

      首先使用序列化将 json 字符串转换为 Object。

      let parsedMapperString = Mapper<Customer>.parseJSONString(JSONString: result) //result is string from json serializer
      

      然后你可以从 JSON 字典的 MapSet 中获取 Customer DTO 到一个 Mappable 对象数组。

      let customerDto = Mapper<Customer>().mapSet(JSONArray: jsonParsed as! [[String : Any]])
      

      希望对您有所帮助。感谢@Nicolas 推动我接近解决方案。

      【讨论】:

        【解决方案5】:

        AlamofireObjectMapper 提供了最简单的解决方案。使用responseArray() 便捷方法:

        Alamofire.request(endpoint).responseArray { (response: DataResponse<[MyMappableClass]>) in
        
                    if let result = response.result.value {
                        // Customer array is here
                    } else if let error = response.result.error {
                        // Handle error
                    } else {
                        // Handle some other not networking error
                    }
                }
        

        【讨论】:

        • 不工作 - 'DataRequest' 类型的值没有成员 'responseArray'
        【解决方案6】:

        将数组转换为json并返回:

        let json = shops.toJSONString()
        let shops = Array<Shop>(JSONString: json)
        

        【讨论】:

          猜你喜欢
          • 2015-10-25
          • 1970-01-01
          • 1970-01-01
          • 2019-07-13
          • 1970-01-01
          • 1970-01-01
          • 2016-10-17
          • 2016-12-31
          • 1970-01-01
          相关资源
          最近更新 更多