Подтвердить что ты не робот

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 корневого массива?

Спасибо.

4b9b3361

Ответ 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)