I'm receiving the following json from the API:
[ { "first_id": 1,
"second_objs": [ { "second_id": 2,
"third_objs": [ { "third_id": 3,
"param": "abcd" }] } ] } ]
And serialising it using ObjectMapper:
class First: NSObject, Mappable {
var first_id: Int?
var second_objs: [Second]?
required init?(_ map: Map){}
func mapping(map: Map) {
first_id <- map["first_id"]
second_objs <- map["second_objs"]
}
}
class Second: NSObject, Mappable {
var second_id: Int?
var third_objs: [Third]?
required init?(_ map: Map){}
func mapping(map: Map) {
second_id <- map["second_id"]
third_objs <- map["third_objs"]
}
}
class Third: NSObject, Mappable {
var third_id: Int?
var param: String?
required init?(_ map: Map){}
func mapping(map: Map) {
third_id <- map["third_id"]
param <- map["param"]
}
}
Now after recieving and modifying that JSON I need to send it back to the API.
However before sending back I need to rename keys "second_objs" and "third_objs" to "something_else_2" and "something_else_3".
[ { "first_id": 1,
"something_else_2": [ { "second_id": 2,
"something_else_3": [ { "third_id": 3,
"param": "abcd" }] } ] } ]
How do I do the renaming in a clean way?
Related
Here is my model
class ResponseDataType: Mappable {
var status: Int?
var message: String?
var info: [Info]?
required init?(map: Map) { }
func mapping(map: Map) {
status <- map["status"]
message <- map["message"]
info <- map["member_info"]
}
}
Here is my JSON
"status": 200,
"data": {
"member_info": [
{
"fullname": "werwerwer",
"type": "werwer",
"profile_image": "sdfsdfsd.jpg",
"email": "wfwe#werwegt",
"contact": ""
}
]
},
"message": "Login Success"
}
Im having a hard time mapping the array inside the data. Please tell me what is wrong with my code.
You forgot the data. It should be like this:
class ResponseDataType: Mappable {
var status: Int?
var message: String?
var data: Data?
required init?(map: Map) { }
func mapping(map: Map) {
status <- map["status"]
message <- map["message"]
data <- map["data"]
}
and your data class:
class Data: Mappable {
var info: [Info]?
required init?(map: Map) { }
func mapping(map: Map) {
info <- map["member_info"]
}
If your Info object conforms to Mappable, everything should work properly in your code. But try to read about Codable protocol, it’s much easier to map objects with it!
I started to use ObjectMapper this week and I'm trying to map a JSON into 2 CustomClasses but I don't known if ObjectMapper has some function to do what I want. First CustomClass has a property of type: [String:CustomClass2] where the index of this Dictionary should be property ID of second CustomObject.
JSON Used:
{
"types": [
{
"id": "mk8QPMSo2xvtSoP0cBUD",
"name": "type 1",
"img": "type_1",
"showCategories": false,
"modalityHint": [
"K7VqeFkRQNXoh2OBxgIf"
],
"categories": [
"mP3MqbJrO5Da1dVAPRvk",
"SlNezp2m3PECnTyqQMUV"
]
}
]
}
Classes Used:
class MyClass: Mappable {
var types:[String:MyClass2] = [String:MyClass2]() //Index should be ID property of MyClass2 Object
required init?(map:Map) {
guard map.JSON["types"] != nil else {
return nil
}
}
func mapping(map: Map) {
types <- map["types"]
}
}
class MyClass2: Mappable {
private var id: String!
private var name: String!
private var img: String!
private var showCategories: Bool!
private var modalityHint: [String]?
private var categories: [String]?
required init?(map: Map) { }
func mapping(map: Map) {
id <- map["id"]
name <- map["name"]
img <- map["img"]
showCategories <- map["showCategories"]
modalityHint <- map["modalityHint"]
categories <- map["categories"]
}
In your JSON the types key is an array not a Dictionary.
Change:
var types:[String:MyClass2] = [String:MyClass2]()
To:
var types:[Class2] = []
Like this:
class MyClass: Mappable {
private var arrayTypes = [MyClass2] {
didSet{
var mapTypes = [String:MyClass2]?
for obj in arrayTypes {
mapTypes[obj.id] = obj
}
types = mapTypes
}
}
var types:[String:MyClass2] = [String:MyClass2]()
required init?(map:Map) {
guard map.JSON["types"] != nil else {
return nil
}
}
func mapping(map: Map) {
arrayTypes <- map["types"]
}
}
My old JSON structure was like this:
{
"parameters": {
"customerId": 9,
"from": "2014-06-05T14:00:00",
"until": "2014-06-05T15:00:00",
"km": 20,
"insurance": false
},
"estimatesPerCategory": {
"2": {
"timeCost": 5,
"kmCost": 6,
...
}
To parse JSON I use ObjectMapper.
This code works very well:
if let myObject = Mapper<CostEstimateResult>().map(JSONObject: JSON) {
}
The class CostEstimateResult looks like this.
class CostEstimateResult : NSObject, Mappable {
var parameters:CostEstimateParameters?
var estimatesPerCategory:[String: CostEstimate]? // CostEstimate.id -> CostEstimate
override init() {}
required convenience init?(map: Map) {
self.init()
self.mapping(map: map)
}
func mapping(map: Map) {
estimatesPerCategory <- map["estimatesPerCategory"]
parameters <- map["parameters"]
}
}
And last but not least my CostEstimate class for estimatesPerCategory
class CostEstimate : NSObject, Mappable {
var timeCost:NSNumber?
...
override init() {}
required convenience init?(map: Map) {
self.init()
self.mapping(map: map)
}
func mapping(map: Map) {
timeCost <- map["timeCost"]
...
}
}
This is working. The mapper in CostEstimateResult will call the mapper in CostEstimates and I get my parsed data.
Now I changed the JSON Structure:
{
"parameters": {
//same like before
},
"estimatesPerCategory": {
"2": {
"total": {
"preTax": {
"value": 1,
"text": "1,00 €"
},
"configTax": false
},
"3": {
//same...
}
}
}
In my opinion in the basic structure nothing changes. estimatesPerCategory is still the same dictionary. The data behind estimatesPerCategory are changed, okay.
The problem is, when I call the mapper ...Mapper<CostEstimateResult>().map... the parameters will be parse, but not the costEstimates. The func mapping in CostEstimate isn't call anymore.
Long story short: It seems that the type of estimatesPerCategory in CostEstimateResult changes with the json structure. I can't figure out which type I need.
Now with new JSON Structure, your Class CostEstimate structure will be changed and a new Class PreTax will be required to be created:
class CostEstimateResult : NSObject, Mappable {
var parameters:CostEstimateParameters?
var estimatesPerCategory:[String: CostEstimate]? // CostEstimate.id -> CostEstimate
override init() {}
required convenience init?(map: Map) {
self.init()
self.mapping(map: map)
}
func mapping(map: Map) {
estimatesPerCategory <- map["estimatesPerCategory"]
}
}
class CostEstimate : NSObject, Mappable {
var total:totalTax?
override init() {}
required convenience init?(map: Map) {
self.init()
self.mapping(map: map)
}
func mapping(map: Map) {
total <- map["total"]
}
}
class totalTax : NSObject, Mappable {
var preTax:PreTax?
var configTax:Bool?
override init() {}
required convenience init?(map: Map) {
self.init()
self.mapping(map: map)
}
func mapping(map: Map) {
preTax <- map["preTax"]
configTax <- map["configTax"]
}
}
class PreTax : NSObject, Mappable {
var value:NSNumber?
var text:String?
override init() {}
required convenience init?(map: Map) {
self.init()
self.mapping(map: map)
}
func mapping(map: Map) {
value <- map["value"]
text <- map["text"]
}
}
I have the following JSON, which I am using together with ObjectMapper:
Open Api
Response snippet
{
"data": [
{
"CategoryName": "רוגע",
"CategoryID": "63",
"CategoryDate": "2016-08-26 02:12:05",
"CategoryImage": "relax.png",
"SubCategoryArray": [
{
"SubCategoryName": "רוגע",
"SubCategoryRefID": "63",
"SubCategoryID": "86",
"SubCategoryDate": "2016-08-28 02:57:07",
"TextArray": [
{
"TextID": "32",
"Text": "<p dir=\"rtl\"><span style=\"font-size:48px\"><strong><span dir=\"RTL\" lang=\"HE\" style=\"font-family:Arial\">פרופורציה</span></strong> . הכול הבל הבלים. חולף כהרף עין. אז לנשום.</span></p>\r\n"
},
My problem is getting the data from "SubCategoryArray", and "TextArray"
I tried to do the following in my mapping:
import UIKit
import ObjectMapper
class APIResult: Mappable {
var data : [dataArray]?
required init?(map: Map){
}
func mapping(map: Map) {
data <- map["data"]
}
}
class dataArray: Mappable{
var CategoryName: String?
var CategoryID: String?
var CategoryDate: String?
var CategoryImage: String?
var SubCategoryArray: SubCategoryArray?
required init?(map: Map){
}
func mapping(map: Map) {
CategoryName <- map["CategoryName"]
CategoryID <- map["CategoryID"]
CategoryDate <- map["CategoryDate"]
CategoryImage <- map["CategoryImage"]
SubCategoryArray <- map["SubCategoryArray"]
}
}
class SubCategoryArray: Mappable {
var SubCategoryName: String?
var SubCategoryRefID: String?
var SubCategoryID: String?
var SubCategoryDate: String?
var TextArray: TextArray?
required init?(map: Map){
}
func mapping(map: Map) {
SubCategoryName <- map["SubCategoryName"]
SubCategoryRefID <- map["SubCategoryRefID"]
SubCategoryID <- map["SubCategoryID"]
SubCategoryDate <- map["SubCategoryDate"]
TextArray <- map["TextArray"]
}
}
class TextArray: Mappable {
var TextID: String?
var Text:String?
required init?(map: Map){
}
func mapping(map: Map) {
TextID <- map["TextID"]
Text <- map["Text"]
// SubCategoryID <- map["SubCategoryID"]
// SubCategoryDate <- map["SubCategoryDate"]
// TextArray <- map["TextArray"]
}
}
Please point what I am doing wrong.
This is how you would map this data
import Foundation
import ObjectMapper
class customData: Mappable {
var categoryName: String = ""
var categoryId: String = ""
var subCategoryArray: [SubCategoryArray] = []
required init?(_ map: Map) {
}
func mapping(map: Map) {
categoryName <- map["data.CategoryName"]
categoryId <- map["data.CategoryID"]
subCategoryArray <- map["data.SubCategoryArray"]
}
}
class SubCategoryArray: Mappable {
var SubCategoryName: String = ""
var SubCategoryRefID: String = ""
var textArray: [TextArray] = []
required init?(_ map: Map) {
}
func mapping(map: Map) {
SubCategoryName <- map["SubCategoryName"]
SubCategoryRefID <- map["SubCategoryRefID"]
textArray <- map["TextArray"]
}
}
class TextArray: Mappable {
var TextID: String = ""
var Text: String = ""
required init?(_ map: Map) {
}
func mapping(map: Map) {
TextID <- map["TextID"]
Text <- map["Text"]
}
}
Let me know if you find any difficulty.
I'm currently using ObjectMapper for Swift for mapping JSON Object from API to model Object
but my restful api return API look like this:
{
success: true,
data:
[{
"stats":{
"numberOfYes":0,
"numberOfNo":2,
"progress":{
"done":false,
"absolute":"2/100",
"percent":2
}
},
"quickStats":null,
"uid":5,
"name":"Flora",
"imageArray":[
"http://s3.com/impr_5329beac79400000",
"http://s3.com/impr_5329beac79400001"
],
"metaData":{
"description":"Floral Midi Dress",
"price":"40$"
}
}]
}
In data node is array i can't look up to mapping with this code
let json = JSON(responseObject!)
for tests in json["impressions"][0] {
let test = Mapper<myTests>().map(tests)
println(test?.impressionID)
}
How should I fix?
Thanks
** Edited **
I found solution similar #tristan_him
ObjectModel mapping structure
class Response: Mappable {
var success: Bool?
var data: [Data]?
required init?(_ map: Map) {
mapping(map)
}
func mapping(map: Map) {
success <- map["success"]
data <- map["data"]
}
}
class Data: Mappable {
var uid: Int?
var name: String?
// add other field which you want to map
required init?(_ map: Map) {
mapping(map)
}
func mapping(map: Map) {
uid <- map["uid"]
name <- map["name"]
}
}
Mapping with Alamofire response
let response: Response = Mapper<Response>().map(responseObject)!
for item in response.data! {
let dataModel: Data = item
println(dataModel.name)
}
You can map the JSON above by using the following class structure:
class Response: Mappable {
var success: Bool?
var data: [Data]?
required init?(_ map: Map) {
mapping(map)
}
func mapping(map: Map) {
success <- map["success"]
data <- map["data"]
}
}
class Data: Mappable {
var uid: Int?
var name: String?
// add other field which you want to map
required init?(_ map: Map) {
mapping(map)
}
func mapping(map: Map) {
uid <- map["uid"]
name <- map["name"]
}
}
Then you can map it as follows:
let response = Mapper<Response>().map(responseObject)
if let id = response?.data?[0].uid {
println(id)
}