iOS - 使用 ObjectMapper 快速映射根 JSON 数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32353026/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 07:29:23  来源:igfitidea点击:

iOS - Map a root JSON array with ObjectMapper in swift

iosjsonswiftnsarray

提问by Nicolas HENAUX

I use the library ObjectMapper to map json with my objects but I have some issues to map a root json Array.

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

This is the received json :

这是收到的 json :

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

This is my object

这是我的对象

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

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

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

I map the json in my controller with

我将控制器中的 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)
}

But it doesn't work, I tried Mapper<[Customer]>().map(json)but it doesn't work too. Finally I tried to create a new swift object CustomerList containing a Customer array but it doesn't work.

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

Do you have an idea of how to map json of a root array ?

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

Thanks.

谢谢。

回答by Nicolas HENAUX

I finally solve my problem :

我终于解决了我的问题:

The mapping method in the controller should be

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

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
}

If it can help someone.

如果它可以帮助某人。

回答by Imanou Petit

Using JSONObjectWithData(::)with the correct conditional downcasting type

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

Your JSON is of type [[String: AnyObject]]. Therefore, with Swift 2, you can use JSONObjectWithData(::)with a conditional downcasting of type [[String: AnyObject]]in order to prevent using NSArrayor AnyObject!:

您的 JSON 类型为[[String: AnyObject]]。因此,在 Swift 2 中,您可以使用JSONObjectWithData(::)类型的条件向下转换,[[String: AnyObject]]以防止使用NSArrayor 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)
}


Mapping to Customerusing mapArray(:)method

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

The ObjectMapper's Mapperclass provides a method called mapArray(:)that has the following declaration:

ObjectMapperMapper类提供了一个调用的方法mapArray(:)有以下声明:

public func mapArray(JSONArray: [[String : AnyObject]]) -> [N]?

public func mapArray(JSONArray: [[String : AnyObject]]) -> [N]?

The ObjectMapperdocumentation states about it:

ObjectMapper关于它的文档指出:

Maps an array of JSON dictionary to an array of Mappable objects

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

Thus, your final code should look something like this:

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

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)
}


Mapping to Customerusing map(:)method

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

The ObjectMapper's Mapperclass provides a method called map(:)that has the following declaration:

ObjectMapperMapper类提供了一个调用的方法map(:)有以下声明:

func map(JSONDictionary: [String : AnyObject]) -> N?

func map(JSONDictionary: [String : AnyObject]) -> N?

The ObjectMapperdocumentation states about it:

ObjectMapper关于它的文档指出:

Maps a JSON dictionary to an object that conforms to Mappable

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

As an alternative to the previous code, the following code shows how to map your JSON to Customerusing map(:):

作为前面代码的替代,以下代码显示了如何将 JSON 映射到Customerusing 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)
}

回答by Bence Pattogato

The easiest solution is provided by AlamofireObjectMapper. Use the responseArray()convenience method:

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
            }
        }

回答by byJeevan

In the same situation in my recent Swift 3, able to solve to get object mapper present in Array as root.

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

First convert json string into a Object Using serialization.

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

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

Then you can get Customer DTO from the MapSet of JSON dictionary to an array of Mappable objects.

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

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

Hope it helps. Thanks to @Nicolas who pushed me close to get solution.

希望能帮助到你。感谢@Nicolas 推动我接近解决方案。

回答by Alcivanio

A good way to solve the problem of mapping a root array with generic object is creating a generic object that creates a list with the object inside the class implementation. Let's see an example of this kind of implementation below:

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

    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
    }

In the code above you'll fill the uppercase variables with your own values. Check that the response return in the closure is a generic object DataResponse from Alamofire, and I did create another one called GenericResponseList. I put inner the "< >" the type of the object that I'll get a list from the server. In my case it was a list of SingleElements.

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

Now, take a look in the implementation of the GenericResponseList below:

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

final class GenericResponseList<T: Mappable>: Mappable {

    var result: [T]?

    required convenience init?(map: Map) {
        self.init()
    }

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

Take a look, I have an variable inside the class that is a list of the generic type I sent to this class.

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

var result: [T]?

So now, when you get you JSON it will convert it in a list of SingleElement.

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

Hope it helped :)

希望它有所帮助:)

回答by Pavel Shorokhov

Convert array to json and back:

将数组转换为 json 并返回:

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