iOS - 在 swift 中使用 ObjectMapper 映射根 JSON 数组
iOS - Map a root JSON array with ObjectMapper in swift
我使用库 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<[Customer]>().map(json)
也不行。
最后,我尝试创建一个包含 Customer 数组的新 swift 对象 CustomerList,但它不起作用。
您知道如何映射 json 根数组吗?
谢谢。
我终于解决了我的问题:
控制器中的映射方法应该是
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
}
如果对某人有帮助。
使用 JSONObjectWithData(::)
和正确的条件向下转换类型
您的 JSON 是 [[String: AnyObject]]
类型。因此,对于 Swift 2,您可以将 JSONObjectWithData(::)
与 [[String: AnyObject]]
类型的条件向下转换一起使用,以防止使用 NSArray
或 AnyObject!
:
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
ObjectMapper
的 Mapper
class 提供了一个名为 mapArray(:)
的方法,它具有以下声明:
public func mapArray(JSONArray: [[String : AnyObject]]) -> [N]?
ObjectMapper
文档对此进行了说明:
Maps an array of JSON dictionary to an array of Mappable objects
因此,您的最终代码应如下所示:
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
ObjectMapper
的 Mapper
class 提供了一个名为 map(:)
的方法,它具有以下声明:
func map(JSONDictionary: [String : AnyObject]) -> N?
ObjectMapper
文档对此进行了说明:
Maps a JSON dictionary to an object that conforms to 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)
}
解决用泛型对象映射根数组问题的一个好方法是创建一个泛型对象,该对象在 class 实现中创建一个包含该对象的列表。让我们在下面看一个这种实现的例子:
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
}
在上面的代码中,您将用自己的值填充大写变量。检查闭包中的响应 return 是否是来自 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"]
}
}
看一下,我在 class 中有一个变量,它是我发送给此 class.
的通用类型的列表
var result: [T]?
所以现在,当你得到 JSON 时,它会将其转换为 SingleElement 列表。
希望对您有所帮助:)
在我最近遇到的同样情况Swift 3,能够解决以root身份获取Array中存在的对象映射器。
首先使用序列化将 json 字符串转换为对象。
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 推动我接近解决方案。
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
}
}
将数组转换为 json 并返回:
let json = shops.toJSONString()
let shops = Array<Shop>(JSONString: json)
我使用库 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<[Customer]>().map(json)
也不行。
最后,我尝试创建一个包含 Customer 数组的新 swift 对象 CustomerList,但它不起作用。
您知道如何映射 json 根数组吗?
谢谢。
我终于解决了我的问题:
控制器中的映射方法应该是
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
}
如果对某人有帮助。
使用 JSONObjectWithData(::)
和正确的条件向下转换类型
您的 JSON 是 [[String: AnyObject]]
类型。因此,对于 Swift 2,您可以将 JSONObjectWithData(::)
与 [[String: AnyObject]]
类型的条件向下转换一起使用,以防止使用 NSArray
或 AnyObject!
:
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
ObjectMapper
的 Mapper
class 提供了一个名为 mapArray(:)
的方法,它具有以下声明:
public func mapArray(JSONArray: [[String : AnyObject]]) -> [N]?
ObjectMapper
文档对此进行了说明:
Maps an array of JSON dictionary to an array of Mappable objects
因此,您的最终代码应如下所示:
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
ObjectMapper
的 Mapper
class 提供了一个名为 map(:)
的方法,它具有以下声明:
func map(JSONDictionary: [String : AnyObject]) -> N?
ObjectMapper
文档对此进行了说明:
Maps a JSON dictionary to an object that conforms to 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)
}
解决用泛型对象映射根数组问题的一个好方法是创建一个泛型对象,该对象在 class 实现中创建一个包含该对象的列表。让我们在下面看一个这种实现的例子:
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
}
在上面的代码中,您将用自己的值填充大写变量。检查闭包中的响应 return 是否是来自 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"]
}
}
看一下,我在 class 中有一个变量,它是我发送给此 class.
的通用类型的列表var result: [T]?
所以现在,当你得到 JSON 时,它会将其转换为 SingleElement 列表。
希望对您有所帮助:)
在我最近遇到的同样情况Swift 3,能够解决以root身份获取Array中存在的对象映射器。
首先使用序列化将 json 字符串转换为对象。
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 推动我接近解决方案。
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
}
}
将数组转换为 json 并返回:
let json = shops.toJSONString()
let shops = Array<Shop>(JSONString: json)