web-dev-qa-db-fra.com

ObjectMapper comment mapper différents objets en fonction de JSON

J'utilise ObjectMapper ( https://github.com/Hearst-DD/ObjectMapper ) pour mapper mon JSON sur des objets Swift.

Disons que j'ai cette structure JSON:

{
  animals: [
    {
      "type": "Cat",
      "weight": 23,
      "catchMice": true
    },
    {
      "type": "Fish",
      "weight": 1,
      "swim": true
    }
  ]
}

J'ai les objets Swift suivants:

class Foo: Mappable {
  var animals: [Animal] = []

  func mapping(map: Map) {
    animals <- map["animals"] //But I want to be able to distinguish between Cat and Fish objects here
  }
}

class Animal: Mappable {
  var type: String?
  var weight: Double?

  required init?(map: Map) {}

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

class Cat: Animal { // How do I make use of this class
  var catchMice: Bool?
}

class Fish: Animal { // How do I make use of this class 
  var swim: Bool?
}

Comment faire la distinction entre Cat et Fish dans mon mappage à l'aide de la clé type dans mes objets JSON? Merci beaucoup!

6
7ball

Détails

xCode 9.1, Swift 4 xCode 8.3, Swift 3.1

Échantillon complet

AnimalsArrayTransformType

import Foundation
import ObjectMapper

class AnimalsArrayTransformType: TransformType {

    public typealias Object = [Animal]
    public typealias JSON = [[String:Any]]

    func transformToJSON(_ value: [Animal]?) -> [[String : Any]]? {
        if let animals = value {
            var result = [[String : Any]]()
            for animal in animals {
                result.append(animal.toJSON())
            }
            return result
        }
        return nil
    }

    func transformFromJSON(_ value: Any?) -> [Animal]? {
        if let animals = value as? [[String: Any]] {
            var resultAnimals = [Animal]()
            for animal in animals {
                if let cat = Cat(JSON: animal) {
                    resultAnimals.append(cat)
                }

                if let fish = Fish(JSON: animal) {
                    resultAnimals.append(fish)
                }
            }
            return resultAnimals
        }
        return nil
    }
}

Cours de cartographie

// Mapping classes

class Foo: Mappable, CustomStringConvertible {
    required init?(map: Map) {
    }

    var animals: [Animal] = []

    func mapping(map: Map) {
        animals <- (map["animals"], AnimalsArrayTransformType())
    }

    var description: String {
        var result = "["
        for (index, animal) in animals.enumerated() {
            result += "\n[\(index)]:\n\(animal.description)"
        }
        result += "\n]\n"
        return result
    }
}

class Animal: Mappable, CustomStringConvertible {
    var type: String?
    var weight: Double?

    var description: String {
        var result = "type: \(String(describing: type))\n"
        result += "weight: \(String(describing: weight))\n"
        return result
    }

    required init?(map: Map) {
        mapping(map: map)
    }

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

class Cat: Animal {
    var catchMice: Bool?

    required init?(map: Map) {
        super.init(map: map)
        if catchMice == nil {
            return nil
        }
    }

    override func mapping(map: Map) {
        super.mapping(map: map)
        catchMice <- map["catchMice"]
    }

    override var description: String {
        var result = super.description
        result += "catchMice: \(String(describing: catchMice))"
        return result
    }
}

class Fish: Animal {
    var swim: Bool?

    required init?(map: Map) {
        super.init(map: map)
        if swim == nil {
            return nil
        }
    }

    override func mapping(map: Map) {
        super.mapping(map: map)
        swim <- map["swim"]
    }

    override var description: String {
        var result = super.description
        result += "swim: \(String(describing: swim))"
        return result
    }
}

fichier json

{
"animals": [
    {
        "type": "Cat",
        "weight": 23,
        "catchMice": true
    },
    {
        "type": "Fish",
        "weight": 1,
        "swim": true
    }
]
}

Utilisation (lire JSON à partir du fichier)

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        readJSON()
    }

    func readJSON() {
        if let path = Bundle.main.path(forResource: "json", ofType: "") {
            do {
                let text = try String(contentsOfFile: path, encoding: .utf8)
                if let dict = try JSONSerialization.jsonObject(with: text.data(using: .utf8)!, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: Any] {
                    if let foo = Foo(JSON: dict) {
                        print(foo)
                        print(foo.toJSON())
                    }
                }
            }catch {
                print("File read error")
            }
        }
    }
}

Résultat

 enter image description here

13

Ma solution utilise la bibliothèque ObjectMapper pour Swift.

Si vous avez ceci:

{
    "animals": [{
            "type": "Cat",
            "weight": 23,
            "catchMice": true
        },
        {
            "type": "Fish",
            "weight": 1,
            "swim": true
        }
    ]
}

Ce site renvoie votre objet complet

import Foundation 
import ObjectMapper 

class Main: Mappable { 

    var animals: [Animals]? 

    required init?(map: Map){ 
    } 

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

class Animals: Mappable { 

    var type: String? 
    var weight: NSNumber? 
    var catchMice: Bool? 

    required init?(map: Map){ 
    } 

    func mapping(map: Map) {
        type <- map["type"] 
        weight <- map["weight"] 
        catchMice <- map["catchMice"] 
    }
} 

J'ai travaillé sur ce projet qui aide à créer vos objets mappables pour la bibliothèque 'ObjectMappable' (Swift).

https://github.com/andreycattalin/JSONtoSwiftObjectMapper

Version en direct: http://izee.ro/andrey/JSONtoSwiftObjectMapper/

0
Andrey

Convertissez d'abord votre chaîne JSON en tableau, puis parcourez chaque dictionnaire du tableau, examinez la valeur de type, puis choisissez le modèle en conséquence pour public func map(JSON: [String: Any]) -> N?.

0
almas
        Simple example as follow
        //
        //  ViewController.Swift
        //  TriyalJSON
        //
        //  Created by Mac on 19/02/19.
        //  Copyright © 2019 shital. All rights reserved.
        //

        import UIKit
        class ViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {
            @IBOutlet weak var mytable: UITableView!
            var arrmain = [GETArrayData]()
            override func viewDidLoad() {
                super.viewDidLoad()
                getdata()
                // Do any additional setup after loading the view, typically from a nib.
            }

            override func didReceiveMemoryWarning() {
                super.didReceiveMemoryWarning()
                // Dispose of any resources that can be recreated.
            }
        func getdata()
        {
            let dict = [
                "name":"shital",
                "address":"pune"
            ]
            APIManager.sharedInstance.getdata(parms: dict, onsuccess: { (responsedata, anystring) in
                print(responsedata,anystring)
                self.arrmain = responsedata
                let str = self.arrmain[0]
                print("Email-",str.email)
                self.mytable.reloadData()
            }) { (error1, error2) in
                print(error1,error2)
            }
            }
            func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                return self.arrmain.count
            }
            func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                        let cell:UITableViewCell = mytable.dequeueReusableCell(withIdentifier: "TableViewCell") as! UITableViewCell
                let str1 = self.arrmain[indexPath.row]
                cell.textLabel?.text = str1.email

                return cell

            }
            func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
                return 400.0
            }
            func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
                let obj = storyboard?.instantiateViewController(withIdentifier: "ViewControllerFrist") as! ViewControllerFrist
        //        ViewControllerFrist.arrpass = self.arrmain
                var strpass = self.arrmain[indexPath.row]
                obj.arrpass = [strpass]
           // obj.arrpass = self.arrmain

                self.navigationController? .pushViewController(obj, animated: true)
            }
        }
        ------------------------------
        ------------------------------
        ------------------------------
        ------------------------------
        ------------------------------
        ------------------------------
        ------------------------------

        //
        //  ViewControllerFrist.Swift
        //  TriyalJSON
        //
        //  Created by Mac on 20/02/19.
        //  Copyright © 2019 shital. All rights reserved.
        //

        import UIKit

        class ViewControllerFrist: UIViewController,UITableViewDelegate,UITableViewDataSource {
            var arrpass = [GETArrayData]()
            static let fristobject = ViewControllerFrist()
            @IBOutlet weak var mytableView: UITableView!
            override func viewDidLoad() {
                super.viewDidLoad()

                // Do any additional setup after loading the view.
            }

            override func didReceiveMemoryWarning() {
                super.didReceiveMemoryWarning()
                // Dispose of any resources that can be recreated.
            }
            func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                print(self.arrpass.count)
                return self.arrpass.count

            }
            func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                let cell:TableViewCell = mytableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
                let str = self.arrpass[indexPath.row]
                cell.textLabel1.text = str.email
                cell.textLabel2.text = "\(str.id)"

                return cell
            }
            func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
                return 300.0
            }

        }

        ------------------------------
        ------------------------------
        ------------------------------
        ------------------------------
        ------------------------------
        ------------------------------
        ------------------------------


        //
        //  APIManager.Swift
        //  TriyalJSON
        //
        //  Created by Mac on 19/02/19.
        //  Copyright © 2019 shital. All rights reserved.
        //

        import UIKit
        import Foundation
        import Alamofire
        import ObjectMapper
        class APIManager: NSObject {

            static let sharedInstance = APIManager()

            func getdata(parms:[String:Any], onsuccess:@escaping([GETArrayData],String?) ->Void,onfailure:@escaping(String?,String?) ->Void)
            {
                let url = URL.init(string: "https://jsonplaceholder.typicode.com/comments")

                let headrs : HTTPHeaders = ["content-type":"application/json"]
                Alamofire.request(url!, method: .get, parameters: parms, encoding: JSONEncoding.default, headers: headrs).responseJSON
                    {
                        response in
                        switch response.result{
                        case .success:

        //                    let string = NSString(data: response.data!, encoding: String.Encoding.utf8.rawValue)
        //                    print("string:\(String(describing: string))")
                            do{
                                let jsonResponse = try JSONSerialization.jsonObject(with: response.data!, options: []) as! AnyObject
                                //let userdetails = Mapper<DataClasss>() .mapArray(JSONObject: jsonResponse)
        //                        let userdetalis = Mapper<GETArrayData>() .mapArray(JSONString: jsonResponse)
                                let userdetails = Mapper<GETArrayData>() .mapArray(JSONObject: jsonResponse)
                                print(jsonResponse)
                                if jsonResponse != nil
                                {
                                    onsuccess(userdetails!,"success")
                                }
                                else
                                {
                                    onfailure((response.error?.localizedDescription)!,"fail")
                                }

                            }catch let parsingError{

                                print("error",parsingError)
                                onfailure((response.error?.localizedDescription)!,"fail")
                            }
                            break
                        case.failure(let error):

                            print(error)
                            onfailure((response.error?.localizedDescription)!,"fail")
                        }

                }
            } 


        }


    --------------------
    --------------------
    --------------------
    --------------------
    --------------------
    --------------------
    //
    //  SecendViewController.Swift
    //  ITGURUassignment
    //
    //  Created by Mac on 18/02/19.
    //  Copyright © 2019 shital. All rights reserved.
    //

    import UIKit

    class SecendViewController: UIViewController {


        @IBOutlet weak var textName: UITextField!

        @IBOutlet weak var txtEmail: UITextField!

        @IBOutlet weak var txtFeatureTitle: UITextField!

        @IBOutlet weak var txtFeatureDescription: UITextView!


        @IBOutlet weak var txtUseCase: UITextView!

        @IBOutlet weak var btnlow: UIButton!



        var strresult = ""


        @IBAction func sendRequestPressed(_ sender: UIButton) {
           var strname = self.textName.text!
            var stremail = self.txtEmail.text!
            var strtitle = self.txtFeatureTitle.text!

            if strname.count <= 0
           {
            print("Enter Frist Name")
            }

           else if stremail.count <= 0 {
                print("enter last name")

            }
            else if strtitle.count <= 0 {
                print("Enter feature title")

            }
            else if self.strresult.count <= 0
            {
                print("Button  not selected:\(strresult)")
            }
            else
            {
                print("Button  selected:\(strresult)")
                let dict = [
                    "AppID":"67-5555545ete",
                    "FeatureTitle":"\(self.txtFeatureTitle.text!)",
                    "UserName":"laura",
                    "UserEmail":"\(self.txtEmail.text!)",
                    "Priority":self.strresult,
                    "Description":"\(self.txtFeatureDescription.text ?? "")",
                    "UseCase":"\(self.txtUseCase.text ?? "")",
                    "DeviceType":"iphone"
                ]
                print(dict)
            }



        }


        @IBAction func btnhighpressed(_ sender: UIButton) {
            self.strresult = "H"
            print(strresult)
            self.btnhigh.setImage(imgselected, for: .normal)
            self.btnlow.setImage(imgunselected, for: .normal)
            self.btnmedium.setImage(imgunselected, for: .normal)
        }


        @IBAction func btnlowpressed(_ sender: UIButton) {
            self.strresult = "L"
            print(strresult)
            self.btnhigh.setImage(imgunselected, for: .normal)
            self.btnlow.setImage(imgselected, for: .normal)
            self.btnmedium.setImage(imgunselected, for: .normal)
        }


        @IBAction func btnmedium(_ sender: UIButton) {
            self.strresult = "M"
            print(strresult)
            self.btnhigh.setImage(imgunselected, for: .normal)
            self.btnlow.setImage(imgunselected, for: .normal)
            self.btnmedium.setImage(imgselected, for: .normal)
        }


        @IBOutlet weak var btnmedium: UIButton!

        @IBOutlet weak var btnhigh: UIButton!

        let imgselected = UIImage.init(named: "Selected")

        let imgunselected = UIImage.init(named: "Unselected")

        override func viewDidLoad() {
            super.viewDidLoad()

            self.btnhigh.setImage(imgunselected, for: .normal)

            self.btnlow.setImage(imgunselected, for: .normal)

            self.btnmedium.setImage(imgunselected, for: .normal)
            // Do any additional setup after loading the view.
        }

        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }

    }

-----------------
-----------------
-----------------
-----------------
-----------------
----------------
----------------
//
//  ViewController.Swift
//  ITGURUassignment
//
//  Created by Mac on 18/02/19.
//  Copyright © 2019 shital. All rights reserved.
//

import UIKit

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {

//    var arrCountryList = [CountryDetails]()
    var arruserdetalis = [USERdetalis]()
//    var usermasterdetails = USERdetalis()

    @IBAction func featureRequest(_ sender: UIButton) {
        let objectforsecviewcontroller = storyboard?.instantiateViewController(withIdentifier: "SecendViewController") as! SecendViewController
        self.navigationController?.pushViewController(objectforsecviewcontroller, animated: true)

    }
    @IBOutlet weak var getdetalitable: UITableView!
    //    @IBAction func nextbtn(_ sender: UIButton) {
//        let vc = storyboard? .instantiateViewController(withIdentifier: "SecendViewController") as! SecendViewController
//        self.navigationController?.pushViewController(vc, animated: true)
//
//    }


    override func viewDidLoad() {
        super.viewDidLoad()
        getdata()

        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
func getdata()
{
    let dict = [
        "name":"shital",
        "roll":"one"
    ]
    APIManager.sharedInstance.getuserdetalis(parms: dict, onsuccess: { (arruserdetalis, anystring) in
        print(arruserdetalis,anystring)
        self.arruserdetalis = arruserdetalis
        var str = arruserdetalis[0]
        self.getdetalitable.reloadData()
    }) { (error1, error2) in
        print(error1,error2)
    }

    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.arruserdetalis.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell:TableViewCell = getdetalitable.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell


        let userdetalis = self.arruserdetalis[indexPath.row]


        cell.textLabel?.text = userdetalis.title ?? ""


        if(userdetalis.isSelected == true)
        {
            cell.btnVote.setTitle("Voted", for: .normal)
            cell.btnVote.isEnabled = false
        }
        else {

            cell.btnVote.setTitle("Vote your vote", for: .normal)
        }

        cell.btnVote.tag = indexPath.row

        cell.btnVote.addTarget(self, action: #selector(voteButtonPressed(sender:)), for: .touchUpInside)


        return cell
    }

    @objc func voteButtonPressed(sender:UIButton){

        let userdetalis = self.arruserdetalis[sender.tag]


        self.getdetalitable.reloadData()


        let dict = [
            "commandtype":"registervote",
            "RequestID":userdetalis.id,
            "usename":userdetalis.title

            ] as [String : Any]

        APIManager.sharedInstance.voteApi(parms: dict, onsuccess: { (response, anystring) in
            print(response,anystring)
            self.getdata()
        }) { (error1, error2) in
            print(error1,error2)
        }



    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 500.0
    }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {


        let third = storyboard?.instantiateViewController(withIdentifier: "ThirdViewController") as! ThirdViewController
       self.navigationController? .pushViewController(third, animated: true)
    }
}
0
shital bhosale