Alamofire ObjectMapper - Extract common fields from all models and map them - ios

There are few fields common in all models returned by api. But they don't come as a separate object. They are there among other fields.
Example of two models :
Event :
[
{
"event":{
"id":3,
"company_id":18,
"archived":false,
"created_by":229,
"updated_by":229,
"owner_id":229,
"subject":"",
"start_date":null,
"end_date":null,
"name":null,
"name_class_name":"",
"related_to":null,
"related_to_class_name":"",
"status":"",
"created_at":"2018-05-07T01:59:38.921-04:00",
"updated_at":"2018-05-07T01:59:38.921-04:00",
"custom_nf":false
}
}
]
Opportunity :
[
{
"opportunity":{
"id":4,
"company_id":18,
"archived":false,
"created_by":229,
"updated_by":229,
"owner_id":229,
"account_id":null,
"name":"",
"lead_source":"",
"amount":null,
"close_date":null,
"probability":null,
"stage":"",
"created_at":"2018-05-07T01:49:55.441-04:00",
"updated_at":"2018-05-07T01:49:55.441-04:00"
}
}
]
As shown, initial fields are common in both (all) models - id, company_id, archived, created_by and so on.
There are tons of projects I have worked with ObjectMapper but didn't encounter this before. I am fully aware of handling nested models, but this is a different case.
Though I can easily handle this by repeating all common fields in all models. But this doesn't sound good.
What I am looking is a way I can create a separate model class with all common fields. But the question is - how would I map that with api response using ObjectMapper ?
Just as an example, this is how I have created Opportunity model :
import UIKit
import ObjectMapper
class Opportunity: NSObject, Mappable {
var id: Int?
var companyId: Int?
var archived: Int?
var createdBy: Int?
var updatedBy: Int?
var ownerId: Int?
var accountId: Int?
var name: String?
var leadSource: String?
var amount: String?
var closeDate: String?
var probability: String?
var stage: String?
var createdAt: String?
var updatedAt: String?
required init?(map: Map) {
}
func mapping(map: Map) {
self.id <- map["id"]
self.companyId <- map["company_id"]
self.archived <- map["archived"]
self.createdBy <- map["created_by"]
self.updatedBy <- map["updated_by"]
self.ownerId <- map["owner_id"]
self.accountId <- map["account_id"]
self.name <- map["name"]
self.leadSource <- map["lead_source"]
self.amount <- map["amount"]
self.closeDate <- map["close_date"]
self.probability <- map["probability"]
self.stage <- map["stage"]
self.createdAt <- map["created_at"]
self.updatedAt <- map["updated_at"]
}
}

You can create base entity and put there common fields.
Example:
import UIKit
import ObjectMapper
class BaseEntity: NSObject, Mappable {
var id: Int?
var companyId: Int?
var archived: Int?
var createdBy: Int?
var updatedBy: Int?
var ownerId: Int?
var name: String?
var createdAt: String?
var updatedAt: String?
required init?(map: Map) {
}
func mapping(map: Map) {
self.id <- map["id"]
self.companyId <- map["company_id"]
self.archived <- map["archived"]
self.createdBy <- map["created_by"]
self.updatedBy <- map["updated_by"]
self.ownerId <- map["owner_id"]
self.name <- map["name"]
self.createdAt <- map["created_at"]
self.updatedAt <- map["updated_at"]
}
}
class Opportunity: BaseEntity {
var accountId: Int?
var leadSource: String?
var amount: String?
var closeDate: String?
var probability: String?
var stage: String?
required init?(map: Map) {
super.init(map: map)
}
override func mapping(map: Map) {
super.mapping(map: map)
self.accountId <- map["account_id"]
self.leadSource <- map["lead_source"]
self.amount <- map["amount"]
self.closeDate <- map["close_date"]
self.probability <- map["probability"]
self.stage <- map["stage"]
}
}
Note: BaseEntity isn't good name, I think you can give better name.

Related

No response from URL in XML parsing - Alamofire Swift 5

I am using XMLMapper with AlamoFire request to get response. URL is working fine on browsers but when I try to use in swift it skips the function. Even I cannot debug the response. Its before parsing, not getting any data or response from the URL. Any idea ??
func xmlParser() {
let urlXml = "https://images.apple.com/main/rss/hotnews/hotnews.rss"
Alamofire.request(urlXml, method: .get).responseXMLObject { (response: DataResponse<RSSFeed>) in
let rssFeed = response.result.value
print(rssFeed?.channel?.items?.first?.title ?? "nil")
}
}
It seems that something is wrong with your model. I managed to map the response from this link.
Try using the following structure and compare it with yours to see the difference:
class RSSFeed: XMLMappable {
var nodeName: String!
var channel: Channel?
required init?(map: XMLMap) {}
func mapping(map: XMLMap) {
channel <- map["channel"]
}
}
class Channel: XMLMappable {
var nodeName: String!
var title: String?
var link: URL?
var description: String?
var language: String?
var copyright: String?
var pubDate: String?
var lastBuildDate: String?
var category: String?
var generator: String?
var docs: URL?
var items: [Item]?
required init?(map: XMLMap) {}
func mapping(map: XMLMap) {
title <- map["title"]
link <- (map["link"], XMLURLTransform())
description <- map["description"]
language <- map["language"]
copyright <- map["copyright"]
pubDate <- map["pubDate"]
lastBuildDate <- map["lastBuildDate"]
category <- map["category"]
generator <- map["generator"]
docs <- (map["docs"], XMLURLTransform())
items <- map["item"]
}
}
class Item: XMLMappable {
var nodeName: String!
var title: String?
var link: URL?
var description: String?
var pubDate: String?
required init?(map: XMLMap) {}
func mapping(map: XMLMap) {
title <- map["title"]
link <- (map["link"], XMLURLTransform())
description <- map["description"]
pubDate <- map["pubDate"]
}
}
Hope this helps.

Json parsing Issue using objectmapper library in swift

I am facing issue with parsing response from server side. I get response in this format
1.)
For first image my model class is working fine. In this I don't null
2.)
For second image response my Model class is not working it's giving nil after parsing.In this I get null in array
My Model class for my api response is this
class GetTodayMyKpiResponse: Mappable{
var status: String?
var myKpiMonth: MyKpiMonthResponse?
var myKpiWeek: MyKpiWeekResponse?
required init?(map: Map){
}
func mapping(map: Map) {
status <- map["status"]
myKpiMonth <- map["myKpiMonth"]
myKpiWeek <- map["myKpiWeek"]
}
}
class MyKpiMonthResponse: Mappable{
var myKpiMonthYear: Double?
var myKpiMonthDetailList: [MyKpiMonthDetailResponse]?
var myKpiMonthList: [MyKpiMonthListReponse]?
required init?(map: Map) {
}
func mapping(map: Map) {
myKpiMonthYear <- map["myKpiMonthYear"]
myKpiMonthDetailList <- map["myKpiMonthDetail"]
myKpiMonthList <- map["myKpiMonthList"]
}
}
class MyKpiMonthDetailResponse: Mappable{
var myKpiMonthDetailOutletCode: String?
var myKpiMonthDetailUnitTiers: [String]?
var myKpiMonthDetailTargetUnits: [String]?
var myKpiMonthDetailBonusIncentive: Double?
var myKpiMonthDetailOutletName: String?
var myKpiMonthDetailModelName: [String]?
var myKpiMonthDetailMonth: String?
var myKpiMonthDetailType: Double?
required init?(map: Map) {
}
func mapping(map: Map) {
myKpiMonthDetailOutletCode <- map["myKpiMonthDetailOutletCode"]
myKpiMonthDetailUnitTiers <- map["myKpiMonthDetailUnitTiers"]
myKpiMonthDetailTargetUnits <- map["myKpiMonthDetailTargetUnits"]
myKpiMonthDetailBonusIncentive <- map["myKpiMonthDetailBonusIncentive"]
myKpiMonthDetailOutletName <- map["myKpiMonthDetailOutletName"]
myKpiMonthDetailModelName <- map["myKpiMonthDetailModelName"]
myKpiMonthDetailMonth <- map["myKpiMonthDetailMonth"]
myKpiMonthDetailType <- map["myKpiMonthDetailType"]
}
}
class MyKpiMonthListReponse: Mappable {
var myKpiMonthMaxUnit: Double?
var myKpiMonthDate: String?
var myKpiMonthBonusAmount: Double?
var myKpiMonthActivatedUnit: Double?
var myKpiMonthMinUnit: Double?
var myKpiMonthCurrentUnit: Double?
var myKpiMonthBonusStatus: String?
var myKpiMonthOutletName: String?
var myKpiMonthOutletAddress: String?
required init?(map: Map) {
}
func mapping(map: Map) {
myKpiMonthMaxUnit <- map["myKpiMonthMaxUnit"]
myKpiMonthDate <- map["myKpiMonthDate"]
myKpiMonthBonusAmount <- map["myKpiMonthBonusAmount"]
myKpiMonthActivatedUnit <- map["myKpiMonthActivatedUnit"]
myKpiMonthMinUnit <- map["myKpiMonthMinUnit"]
myKpiMonthCurrentUnit <- map["myKpiMonthCurrentUnit"]
myKpiMonthBonusStatus <- map["myKpiMonthBonusStatus"]
myKpiMonthOutletName <- map["myKpiMonthOutletName"]
myKpiMonthOutletAddress <- map["myKpiMonthOutletAddress"]
}
}
class MyKpiWeekResponse: Mappable{
var myKpiWeekDetail: [MyKpiWeekDetailResponse]?
var myKpiWeekList: [MyKpiWeekListResponse]?
var myKpiWeekYear: Double?
var myKpiWeekMonth: Double?
required init?(map: Map) {
}
func mapping(map: Map) {
myKpiWeekDetail <- map["myKpiWeekDetail"]
myKpiWeekList <- map["myKpiWeekList"]
myKpiWeekYear <- map["myKpiWeekYear"]
myKpiWeekMonth <- map["myKpiWeekMonth"]
}
}
class MyKpiWeekDetailResponse: Mappable{
var myKpiWeekDetailEndDate: String?
var myKpiWeekDetailUnitTiers: [String]?
var myKpiWeekDetailOutletName: String?
var myKpiWeekDetailStartDate: String?
var myKpiWeekDetailType: Double?
var myKpiWeekDetailModelName: [String]?
var myKpiWeekDetailTypeOfReward: String?
var myKpiWeekDetailOutletCode: String?
var myKpiWeekDetailTargetUnits: [String]?
required init?(map: Map) {
}
func mapping(map: Map) {
myKpiWeekDetailEndDate <- map["myKpiWeekDetailEndDate"]
myKpiWeekDetailUnitTiers <- map["myKpiWeekDetailUnitTiers"]
myKpiWeekDetailOutletName <- map["myKpiWeekDetailOutletName"]
myKpiWeekDetailStartDate <- map["myKpiWeekDetailStartDate"]
myKpiWeekDetailType <- map["myKpiWeekDetailType"]
myKpiWeekDetailModelName <- map["myKpiWeekDetailModelName"]
myKpiWeekDetailTypeOfReward <- map["myKpiWeekDetailTypeOfReward"]
myKpiWeekDetailOutletCode <- map["myKpiWeekDetailOutletCode"]
myKpiWeekDetailTargetUnits <- map["myKpiWeekDetailTargetUnits"]
}
}
class MyKpiWeekListResponse: Mappable {
var myKpiWeekBonusStatus: String?
var myKpiWeekEndDate: String?
var myKpiWeekActivatedUnit: Double?
var myKpiWeekStartDate: String?
var myKpiWeekMinUnit: Double?
var myKpiWeekCurrentUnit: Double?
var myKpiWeekOutletName: String?
var myKpiWeekTypeOfReward: String?
var myKpiWeekOutletAddress: String?
var myKpiWeekMaxUnit: Double?
required init?(map: Map) {
}
func mapping(map: Map) {
myKpiWeekBonusStatus <- map["myKpiWeekBonusStatus"]
myKpiWeekEndDate <- map["myKpiWeekEndDate"]
myKpiWeekActivatedUnit <- map["myKpiWeekActivatedUnit"]
myKpiWeekStartDate <- map["myKpiWeekStartDate"]
myKpiWeekMinUnit <- map["myKpiWeekMinUnit"]
myKpiWeekCurrentUnit <- map["myKpiWeekCurrentUnit"]
myKpiWeekOutletName <- map["myKpiWeekOutletName"]
myKpiWeekTypeOfReward <- map["myKpiWeekTypeOfReward"]
myKpiWeekOutletAddress <- map["myKpiWeekOutletAddress"]
myKpiWeekMaxUnit <- map["myKpiWeekMaxUnit"]
}
}
If there is no data available then send empty array not null. Even in myKpiMonthList doesn't contain null array. There is no logic that null value in array at index 2.
You can send empty string or empty array even. Still there is no any logic for the null value.
Either handle all null value from server side else it always crash.

Mapping nested objects from root node is not working

Using ObjectMapper(https://github.com/Hearst-DD/ObjectMapper), I'm doing JSON conversion to Swift Objects. App is crashing while accessing user.profession.
Basically, I do not know how to parse another mappable object inside the model with same JSON map root node I think, I'm doing it wrong. I can't find the documentation for the same anywhere.
JSON dictionary:
user: {
"name": "Dinesh",
"url": "https://dinaraja.me",
"company": "IIINC",
"designation": "Developer"
}
Model:
struct User: Mappable {
var name: String!
var url: URL!
var profession: Profession!
init(_ map: Map) {
name <- map["name"]
url <- map["url"]
profession <- map // FIXME: It's not working. Find out what we do here is right/wrong
}
}
struct Profession: Mappable {
var company: String!
var designation: String!
init(_ map: Map) {
company <- map["company"]
designation <- map["designation"]
}
}
What I did:
let user = Mapper<User>().map(myJSONDictionary)
print(user.profession.company) //FIXME: Crashes here
Any help would be appreciated.
Since profession model its not included directly in user json model you should not use object mapper <- operator in this case. Instead you should initialize new Profession object directly from user mapping function
struct User: Mappable {
var name: String!
var url: URL!
var profession: Profession!
init(map: Map) {
}
mutating func mapping(map: Map) {
name <- map["name"]
url <- map["url"]
profession = Profession(map: map)
}
}
struct Profession: Mappable {
var company: String!
var designation: String!
init(map: Map) {
company <- map["company"]
designation <- map["designation"]
}
mutating func mapping(map: Map) {
company <- map["company"]
designation <- map["designation"]
}
}

How to append object in Mappable class(Model). iOS swift

In my app, I'm using Alamofire-ObjectMapper.
I have a [OrderDetailSecond]. now i want to use for loop for this array and when isRxMedicine == 1 i want to add that object in any array so i can display that in my UITableView.
here is my code
this is my model
class OrderDetailSecond: Mappable {
var id : Int?
var isRxMedicine : Int?
var medicineTypeId : String?
var name : String?
var orderId : String?
var price : String?
var quentity : Int?
var strength : String?
required init?(_ map: Map){
}
func mapping(map: Map) {
id <- map["id"]
isRxMedicine <- map["is_rx_medicine"]
medicineTypeId <- map["medicine_type_id"]
name <- map["name"]
orderId <- map["order_id"]
price <- map["price"]
quentity <- map["qty"]
strength <- map["strengh"]
}
}
now here i am trying to add objects in new element
if let Rx_OrderDetail = self.orderdetailInstance, Rx_detail = Rx_OrderDetail.result{
let detailArray = Rx_detail[0].orederDetail
if let orderdata = detailArray
{
for RxDataFilter in orderdata
{
if (RxDataFilter.isRxMedicine == 1)
{
array?.append(RxDataFilter)
}
}
elementConunt = orderdata.count
}
return elementConunt
}
but its not working
Note: orderdata is in form [OrderDetailSecond]

ObjectMapper - initialize object IOS

Simple thing that is giving me a headache - how to initialize an object that conforms to mappable protocol, without any JSON yet.
What I would like to do, is simply initialise empty User object in code like this:
let user = User()
however that gives me error:
"missing argument for parameter #1 in call"
I was able to do it in version 0.14 with swift 1.2, but now it doesnt work. Do you guys know how to do it now in swift 2 and new Object Mapper ? (I know how to initialize it with json etc, I just want to initialize that object for other purposes and I cant figure out how)
class User: Mappable {
var username: String?
var age: Int?
var weight: Double!
var array: [AnyObject]?
var dictionary: [String : AnyObject] = [:]
var bestFriend: User? // Nested User object
var friends: [User]? // Array of Users
var birthday: NSDate?
required init?(_ map: Map) {
}
// Mappable
func mapping(map: Map) {
username <- map["username"]
age <- map["age"]
weight <- map["weight"]
array <- map["arr"]
dictionary <- map["dict"]
bestFriend <- map["best_friend"]
friends <- map["friends"]
birthday <- (map["birthday"], DateTransform())
}
}
please help!
The following should work:
class User: NSObject, Mappable {
var username: String?
var age: Int?
var weight: Double!
var array: [AnyObject]?
var dictionary: [String : AnyObject] = [:]
var bestFriend: User? // Nested User object
var friends: [User]? // Array of Users
var birthday: NSDate?
override init() {
super.init()
}
convenience required init?(_ map: Map) {
self.init()
}
// Mappable
func mapping(map: Map) {
username <- map["username"]
age <- map["age"]
weight <- map["weight"]
array <- map["arr"]
dictionary <- map["dict"]
bestFriend <- map["best_friend"]
friends <- map["friends"]
birthday <- (map["birthday"], DateTransform())
}
}
Fixed version of above answer:
init() {}
required convenience init?(_ map: Map) { self.init() }

Resources