web-dev-qa-db-ja.com

iOS-ルートJSON配列をObjectMapperで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をマップする方法のアイデアはありますか?

ありがとう。

35
Nicolas HENAUX

私は最終的に私の問題を解決します:

コントローラーのマッピング方法は

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
}

それが誰かを助けることができるなら。

56
Nicolas HENAUX

正しい条件付きダウンキャスティングタイプでJSONObjectWithData(::)を使用する

JSONのタイプは_[[String: AnyObject]]_です。したがって、Swift 2)では、_NSArrayまたは_[[String: AnyObject]]_の使用を防ぐために、JSONObjectWithData(::)をタイプ_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へのマッピング

ObjectMapperMapperクラスは、次の宣言を持つ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)
}
_

map(:)メソッドを使用したCustomerへのマッピング

ObjectMapperMapperクラスは、次の宣言を持つmap(:)というメソッドを提供します。

func map(JSONDictionary: [String : AnyObject]) -> 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)
}
_
9
Imanou Petit

最も簡単な解決策は 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
            }
        }
3
Bence Pattogato

私の最近のSwift 3の同じ状況で、ルートとしてオブジェクトマッパーが配列に存在するように解決できます。

最初に、シリアル化を使用してJSON文字列をオブジェクトに変換します。

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

次に、JSON辞書のMapSetからMappableオブジェクトの配列にCustomer DTOを取得できます。

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

それが役に立てば幸い。ソリューションを取得するために私を近づけた@Nicolasに感謝します。

2
byJeevan

配列をjsonに変換して戻す:

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

ルート配列を汎用オブジェクトにマッピングする問題を解決する良い方法は、クラス実装内のオブジェクトでリストを作成する汎用オブジェクトを作成することです。以下に、この種の実装の例を見てみましょう。

    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のリストに変換されます。

それが助けたことを願っています:)

1
Alcivanio