IOS - сопоставление корневого массива JSON с ObjectMapper в быстром
Я использую библиотеку 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)
, но он тоже не работает.
Наконец, я попытался создать новый быстрый объект CustomerList, содержащий массив Customer, но он не работает.
Есть ли у вас представление о том, как сопоставить json корневого массива?
Спасибо.
Ответы
Ответ 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(::)
с правильным условным типом downcasting
Ваш 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 mapping operation here */
} else {
/* ... */
}
}
catch let error as NSError {
print(error)
}
Отображение Customer
с использованием метода mapArray(:)
Класс ObjectMapper
Mapper
предоставляет метод под названием mapArray(:)
, который имеет следующее объявление:
public func mapArray(JSONArray: [[String : AnyObject]]) -> [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)
}
Сопоставление с Customer
с использованием метода map(:)
Класс ObjectMapper
Mapper
предоставляет метод под названием map(:)
, который имеет следующее объявление:
func map(JSONDictionary: [String : AnyObject]) -> N?
В документации ObjectMapper
говорится об этом:
Сопоставляет словарь JSON с объектом, который соответствует Mappable
В качестве альтернативы предыдущему коду, следующий код показывает, как сопоставить JSON с Customer
с помощью map(:)
:
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
Самое простое решение предоставляется 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
}
}
Ответ 4
Хорошим способом решения проблемы сопоставления корневого массива с общим объектом является создание универсального объекта, который создает список с объектом внутри реализации класса. Ниже приведен пример такой реализации:
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
}
В приведенном выше коде вы заполняете переменные верхнего регистра своими собственными значениями. Убедитесь, что ответ возвращается в закрытии - это общий объект DataResponse от Alamofire, и я создал еще один, называемый 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.
Надеюсь, что это помогло:)
Ответ 5
В той же ситуации в моей недавней Swift 3, способной решить, чтобы получить отображение объекта в массиве как root.
Сначала преобразуйте строку json в сериализацию Object Using.
let parsedMapperString = Mapper<Customer>.parseJSONString(JSONString: result) //result is string from json serializer
Затем вы можете получить Customer DTO из словаря MapSet из JSON в массив объектов Mappable.
let customerDto = Mapper<Customer>().mapSet(JSONArray: jsonParsed as! [[String : Any]])
Надеюсь, это поможет. Спасибо @Nicolas, который подтолкнул меня близко к решению.
Ответ 6
Преобразование массива в json и обратно:
let json = shops.toJSONString()
let shops = Array<Shop>(JSONString: json)