-1

We have a json payload:

{
  "aps": {
    "alert": {
      "title": "Payload",
      "body": "Lets map this thing"
    },
  },
  "type": "alert",
  "message": "This is a message",
}

The custom object has been created:

class PushNotificationDetail {

var title: String //operation
var body: String //message
var type: detailType
var message: String?

init(title: String, body: String, type: detailType, message: string?){

    self.title = title
    self.body = body
    self.type = type
    self.message = message
}
}

The problem is mapping it correctly to the created object, what would be the best way to achieve this?

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
SwiftyJD
  • 5,257
  • 7
  • 41
  • 92
  • https://www.raywenderlich.com/150322/swift-json-tutorial-2 or https://developer.apple.com/swift/blog/?id=37 – CodeNinja Oct 06 '17 at 16:07
  • I think you should put title and body inside model named `alert` or `detailType` (I think you are using `detailType`, by the way you should name your types with capital letters e.g DetailType) – 3stud1ant3 Oct 06 '17 at 16:10
  • 1
    What problem are you actually having with the mapping? Your question shows no attempt to do any mapping to any attempt to parse the JSON. – rmaddy Oct 06 '17 at 16:12
  • Sufficiently discussed here: https://stackoverflow.com/a/45603025/341994 – matt Oct 06 '17 at 17:06

2 Answers2

3

You should use Swift4 Codable protocol to initialise your object from the json returned by the api. You will need to restructure your structure to match the data returned by the api:

struct PushNotificationDetail: Codable, CustomStringConvertible  {
    let aps: Aps
    let type: String
    let message: String?
    var description: String { return aps.description + " - Type: " + type + " - Message: " + (message ?? "") }
}
struct Aps: Codable, CustomStringConvertible {
    let alert: Alert
    var description: String { return alert.description }
}
struct Alert: Codable, CustomStringConvertible {
    let title: String
    let body: String
    var description: String { return "Tile: " + title + " - " + "Body: " + body }
}

extension Data {
    var string: String { return String(data: self, encoding: .utf8) ?? "" }
}

Playground Testing

let json = """
{"aps":{"alert":{"title":"Payload","body":"Lets map this thing"}},"type":"alert","message":"This is a message"}
"""

if let pnd = try? JSONDecoder().decode(PushNotificationDetail.self, from:  Data(json.utf8)) {
    print(pnd)  // "Tile: Payload - Body: Lets map this thing - Type: alert - Message: This is a message\n"
    // lets encode it
    if let data = try? JSONEncoder().encode(pnd) {
        print(data.string)  // "{"aps":{"alert":{"title":"Payload","body":"Lets map this thing"}},"type":"alert","message":"This is a message"}\n"
        print(data == Data(json.utf8))  // true
    }
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
0

You can do this with a failable initialiser in your PushNotificationDetail class and a chained guard statement:

init?(jsonDict: [String : Any]) {

    guard let typeString : String = jsonDict[“type”] as? String,
        let message: String = jsonDict[“message”] as? String,
        let aps : [String : Any] = jsonDict[“aps”] as? [String : Any],
        let alert : [String : String] = aps[“alert”] as? [String : String],
        let title : String = alert[“title”],
        let body : String = alert[“body”] else { return nil }

    // implement some code here to create type from typeString 

    self.init(title: title, body: body, type: type, message: message)

}

Hope that helps.

Marcus
  • 2,153
  • 2
  • 13
  • 21