Im getting an error while try use Alamofire and AlamofireObjectMapper
My function to call api
static func getUberIntegration(completion: #escaping ([Integrations]?) -> ()) {
let url = "\(Url.baseURL())/integrations"
let headers = Headers.authorization()
Alamofire.request(url, headers: headers).responseArray { (response: DataResponse<[Integrations]>) in
let integration = response.result.value
print(integration!)
completion(integration)
}
}
Model
class Integrations: Object, Mappable {
#objc dynamic var id: Int32 = 0
#objc dynamic var type: String = ""
#objc dynamic var active: Bool = false
override static func primaryKey() -> String? {
return "id"
}
required convenience init?(map: Map) {
self.init()
}
func mapping(map: Map) {
id <- map["id"]
type <- map["type"]
active <- map["active"]
}
}
Response from API when status code 200 is
{
"id": 120,
"type": "Integration",
"active": true
}
Anyone can explain why this issue is happening? When i print in debug status code is return code 200 but can't read json data
I get this error
Error Domain=com.alamofireobjectmapper.error Code=2 "ObjectMapper
failed to serialize response."
Related
So I'm working with a weather API:
https://api.darksky.net/forecast/88d117d813f2014a1ce7f3de6a00c720/50.909698,-1.404351
The thing I want to achieve is getting all the precipIntensity from each minute into an array. This way I can make a graph where the Y is the precipIntensity and the X is array.count (which would count up to 61 with this API).
So this is my code in the ViewController:
func downloadWeatherDetails(completed: DownloadComplete) {
// Alamofire Download
let currentWeatherURL = URL(string: WeatherURL)!
Alamofire.request(currentWeatherURL).responseObject { (response: DataResponse<WeatherResponse>) in
let Forecast = response.result.value
if let minutelyForecast = Forecast?.minutelyForecast {
for forecast in minutelyForecast {
print(forecast.time)
print(forecast.precipIntensity)
}
}
}
}
And my Class file is as follows:
class WeatherResponse: Mappable {
var summary: String!
var minutelyForecast: [Forecast]?
required init?(map: Map) {
}
func mapping(map: Map) {
summary <- map["minutely.summary"]
minutelyForecast <- map["minutely.data"]
}
}
class Forecast: Mappable {
var time: String!
var precipIntensity: String!
required init?(map: Map) {
}
func mapping(map: Map) {
time <- map["time"]
precipIntensity <- map["precipIntensity"]
}
}
However the print(forecast.precipIntensity) prints out nil, 61 times.
How do I get this info?
And how can I put it into an array to make it into a graph and continue with my work?
Thanks in advance.
The problem with your code was that time and precipIntensity aren't String values, but numbers.
class Forecast: Mappable {
var time: Int!
var precipIntensity: Double!
...
}
Extracting precipitation data :
func downloadWeatherDetails(completed: DownloadComplete) {
// Alamofire Download
let currentWeatherURL = URL(string: WeatherURL)!
Alamofire.request(currentWeatherURL).responseObject { (response: DataResponse<WeatherResponse>) in
let Forecast = response.result.value
if let minutelyForecast = Forecast?.minutelyForecast {
// Data is already sorted from the API
// but you could be sure nothing happened while decoding
// by using `sorted()`
let minutelyPrecipIntensity = minutelyForecast
.sorted { $0.time < $1.time }
.flatMap { $0.precipIntensity }
}
}
}
Edit: Removed Codable answer
I am using the alamofire to get response JSON from server, then using ObjectMapper to map string to Realm object.
The realm object is:
class SolutionVideo: Object, Mappable {
dynamic var svID = 0
dynamic var solutionTitle = ""
dynamic var videoName = ""
dynamic var relatedInfo = ""
dynamic var shortDesc = ""
override static func primaryKey() -> String? {
return "svID"
}
required convenience init?(_ map: Map) {
self.init()
}
func mapping(map: Map) {
svID <- map["svID"]
solutionTitle <- map["solutionTitle"]
videoName <- map["videoName"]
relatedInfo <- map["relatedInfo"]
shortDesc <- map["shortDescription"]
}
}
The json string is:
[
{
"svID": "10",
"solutionTitle": "Video10",
"videoName": "Video10",
"realtedInfo": "",
"shortDescription": ""
},
{
"svID": "9",
"solutionTitle": "Video9",
"videoName": "Video9",
"realtedInfo": "",
"shortDescription": ""
}
]
in my viewController:
#IBAction func updateBtn(sender: AnyObject) {
// download file to update Realm
let url = "http://janicedemo.com/updates.json"
Alamofire.request(.GET, url).responseArray { (response: Response<[SolutionVideo], NSError>) in
let Array = response.result.value
print(Array)
if let Array = Array {
for video in Array {
let dbURL = Realm.Configuration.defaultConfiguration.fileURL
let realm = try! Realm(fileURL: dbURL!)
try! realm.write{
print("will save")
realm.add(video, update: true)
}
}
}
}
The problem is that I can add the object successfully. But the svID(primark key) keeps 0, instead of 10 or 9 (set in JSON). Is it because I have set default value to svID? Can someone gives me a hint? Thanks
Try
class SolutionVideo: Object, Mappable {
dynamic var svID = 0
dynamic var solutionTitle = ""
dynamic var videoName = ""
dynamic var relatedInfo = ""
dynamic var shortDesc = ""
func setCompoundID(id: Int) {
self.svID = svID
compoundKey = compoundKeyValue()
}
func setCompoundID(id: Int) {
self.solutionTitle = solutionTitle
compoundKey = compoundKeyValue()
}
func setCompoundID(id: Int) {
self.videoName = videoName
compoundKey = compoundKeyValue()
}
func setCompoundID(id: Int) {
self.relatedInfo = relatedInfo
compoundKey = compoundKeyValue()
}
func setCompoundID(id: Int) {
self.shortDesc = shortDesc
compoundKey = compoundKeyValue()
}
dynamic lazy var compoundKey: String = self.compoundKeyValue()
override static func primaryKey() -> String? {
return “compoundKey”
}
func compoundKeyValue() -> String {
return "\(svID)\(solutionTitle)\(videoName)\(relatedInfo)\(shortDesc)”
}
}
The main thing I can think of is that the primary key values are coming down as strings instead of proper integers (i.e., "10" instead of simply 10). It's possible that the mapper isn't smart enough to handle conversion of strings to integers, so it's just defaulting to 0.
According to the ObjectMapper documentation, you should be able to perform this conversion inline in your mapping function:
svID <- (map["svID"], TransformOf<Int, String>(fromJSON: { Int($0!) }, toJSON: { $0.map { String($0) } }))
Also, as a sidenote, I noticed that one of your JSON key names has a spelling error: "realtedInfo". So I'd recommend double-checking that works too. :)
I am using AlamofireObjectMapper for mapping JSON response to response objects.
In my application i have JSON response like follow:
{ "HasError": false, "ErrorMessage": "", "SuccessMessage": "Login success", "data": { <Dict> } }
Here Dict can be any response object. How can i create mappable response object ?
My assumption is something like this:
class ResponseModel: BaseModel {
var hasError: Bool?
var errorMessage: String?
var successMessage: String?
var data: ResponseData?
required init?(_ map: Map) {
super.init(map)
}
override func mapping(map: Map) {
super.mapping(map)
hasError <- map["HasError"]
errorMessage <- map["ErrorMessage"]
successMessage <- map["SuccessMessage"]
data <- map["data"]
}
}
Where ResponseData is:
class ResponseData<T: Mappable>: Mappable {
var responseData: T?
required init?(_ map: Map){
}
func mapping(map: Map) {
responseData <- map["data"]
}
}
As a lot of people has this error, so do I, I have no idea why the "responseObject cannot be invoked with argument list of type ((JSONResponse>) -> _)"
I'm also using mapping for JSON with Alamofire+ObjectMapper
Do anybody have an idea, whats wrong with Alamofire, its very often error, may be any thoughts about understanding Alamofire?
import Foundation
import Alamofire
import AlamofireObjectMapper
import ObjectMapper
public protocol Mappable {
static func newInstance(map: Map) -> Mappable?
mutating func mapping(map: Map)
}
class JMapping {
func getJSON() {
let url = "http://www.somestringToJson/json.json"
Alamofire
.request(.GET, url, parameters: nil)
.responseObject { (response: JSONResponse?) in
println(response?.title)
if let events = response?.events {
for event in events {
println(event.id)
println(event.title)
}
}
}
}
}
class JSONResponse: Mappable {
var title: String?
var id: String?
var events: [EventsResponse]?
class func newInstance(map: Map) -> Mappable? {
return JSONResponse()
}
func mapping(map: Map) {
title <- map["title"]
id <- map["id"]
events <- map["events"]
}
}
class EventsResponse: Mappable {
var title: String?
var id: String?
var content: [ContentResponse]?
class func newInstance(map:Map) -> Mappable? {
return EventsResponse()
}
func mapping(map: Map) {
title <- map["title"]
id <- map["id"]
content <- map["content"]
}
}
class ContentResponse: Mappable{
var content_type: String?
var visible: Bool?
var data: NSArray?
class func newInstance(map: Map) -> Mappable? {
return ContentResponse()
}
func mapping(map: Map) {
content_type <- map["content_type"]
visible <- map["visible"]
data <- map["data"]
}
}
Alamofire.request(.GET, "http://yoururl.de")
.response { (request, response, data, error) in
}
Basic alamofire get request looks like this. Response is called when request is finished.
After that I would recommend to use SwiftyJSON and convert your responsed data.
if let data = (responseBody as NSString).dataUsingEncoding(NSUTF8StringEncoding) {
let json = JSON(data: data)
println(json)
}
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)
}