evermeer / AlamofireJsonToObjects

An Alamofire extension which converts JSON response data into swift objects using EVReflection
Other
161 stars 28 forks source link

Custom mapping problem #9

Closed Narayane closed 9 years ago

Narayane commented 9 years ago

Hi,

I try to use AlamofireJsonToObjects 1.2.0 with a custom mapping.

Alamofire.request(.GET, "http://myendpointurl/", parameters: nil).responseArray { (response: Result<[Site]>) -> Void in NSLog("sites count: %d", response.value!.count) }

class Site: EVObject {

/*var id: NSNumber?
var openDataId: NSString?
var title: NSString?
var nature: NSString?
var latitude: NSNumber?
var longitude: NSNumber?
var startDate: NSDate?
var endDate: NSDate?
var carNuisanceLevel: NSNumber?
var carNuisanceDescription: NSString?
var bikeNuisanceLevel: NSNumber?
var bikeNuisanceDescription: NSString?
var pedestrianNuisanceLevel: NSNumber?
var pedestrianNuisanceDescription: NSString?
var contactUrl: NSString?*/

var id: Int?
var openDataId: String?
var title: String?
var nature: String?
var latitude: Double?
var longitude: Double?
var startDate: NSDate?
var endDate: NSDate?
var carNuisanceLevel: Double?
var carNuisanceDescription: String?
var bikeNuisanceLevel: Double?
var bikeNuisanceDescription: String?
var pedestrianNuisanceLevel: Double?
var pedestrianNuisanceDescription: String?
var contactUrl:String?

override func propertyMapping() -> [(String?, String?)] {
    return [("openDataId","record_id"), ("startDate","start_date"), ("endDate","end_date"), ("carNuisanceLevel","nuisance_car"), ("carNuisanceDescription","nuisance_car_description"), ("bikeNuisanceLevel","nuisance_bike"), ("bikeNuisanceDescription","nuisance_bike_description"), ("pedestrianNuisanceLevel","nuisance_pedestrian"), ("pedestrianNuisanceDescription","nuisance_pedestrian_description"), ("contactUrl","myfeelback_url")]
}

}

In this configuration (Swift types use Int, String), I have this error on each field binding try

WARNING: The class 'Site' is not key value coding-compliant for the key 'carNuisanceLevel' There is no support for optional type, array of optionals or enum properties. As a workaround you can implement the function 'setValue forUndefinedKey' for this. See the unit tests for more information

When I use other configuration (ObjC types use NSNumber, NSString), I don't have warning message anymore but a breakpoint (I suppose on each field binding try) in init method assemblor code of my relative class

0x9c6e0 <+0>:   pushl  %ebp
0x9c6e1 <+1>:   movl   %esp, %ebp
0x9c6e3 <+3>:   pushl  %esi
0x9c6e4 <+4>:   subl   $0x84, %esp
0x9c6ea <+10>:  calll  0x9c6ef                   ; <+15> at Site.swift:12
0x9c6ef <+15>:  popl   %eax
0x9c6f0 <+16>:  movl   0x8(%ebp), %ecx
0x9c6f3 <+19>:  movl   %ecx, -0x8(%ebp)

-> 0x9c6f6 <+22>: movl $0x0, -0x10(%ebp)

What am I doing wrong?

Other question, for example for startDate, I get a string in UTC format, is AlamofireJsonToObjects able to manage conversion to NSDate natively or do I add some specific process ?

Thanks in advance.

evermeer commented 9 years ago

For the optional numbers there are a couple of workarounds. Instead of an optional you could default it to 0 or some other value that you know that could be treated the same way as a nil var id: Int = 0 or you could use an optional NSNumber var id: NSNumber? And If you don't want a different type then add a 'set value forUndefinedKey' function like there is in the unit tests.

An Optional String is treated by Swift as an optional object instead of an optional type. so you don't need to change it to an optional NSString

But then... You have a crash when it tries to set the NSNumber...

AlamofireJsonToObjects is largely based on EVReflection. I did some tests with parsing json data to an optional NSNumber and I could not find a bug there. Could you try your app again and then when it stops at that breakpoint, could you pleas move the trace hyrarchy up do the first where you see the line of swift code that is causing the breakpoint. I am wondering if it's the anyObject.setValue call that is causing this or if it's something else.

You are right, at the moment there is no support for automatic parsing of the string to a NSDate. The question would be what kind of date formatter I should use... Maybe I should add an option to EVReflection that you would be able to configure a date formatter. What do you think?

Narayane commented 9 years ago

Calls hierarchy

bug

I come from Android world where we have an amazing api called retrofit where it is possible to define customs converters for that at rest client level.

So yes, add an option to define a custom date formatter will be great in a first time (UTC by default if no definition).

Narayane commented 9 years ago

Hi,

does calls hierarchy screenshot allow you identifying my problem?

Regards.

evermeer commented 9 years ago

Not yet. This weekend I have more time to investigate this problem. Are you sure you have an array of objects? You are calling the .responseArray If it's an object you should call .responseObject But then again it should not crash.

In your stack trace I do see that it stops in the init of a Site. This weekend I will at least add a conversion for String to NSDate where you will be able to use a custom dateConverter. I will also add tests for that. Hopefully I will find out what's wrong wile doing that.

It would be nice if you could supply me a .json file where you now have a crash with. Together with the object definition above I can create a unit test for your problem

Narayane commented 9 years ago

Hi,

I sended to you an email with useful information to debug.

You can also copy code of my previous posts to be in the "same conditions" (Alamofire + AlamofireJsonToObjects).

Thanks.

evermeer commented 9 years ago

There is now a new version of EVReflection with support for NSDate and NSDateFormatter. If you want to use a custom dateformat, then set it using EVReflection.setDateFormat. It will be used for both parsing to and from json.

evermeer commented 9 years ago

I replied on your email. Are you now able to parse the json?

Narayane commented 9 years ago

Hi,

"I replied on your email."

I received no reply. I also checked my spam folder just in case. Nothing.

evermeer commented 9 years ago

Hi, I just send it to you again.

I created a unit test for your feed. See the code below (You only need to fix the url)

//
//  issueTest.swift
//  AlamofireJsonToObjects
//
//  Created by Edwin Vermeer on 10/7/15.
//  Copyright © 2015 evict. All rights reserved.
//

import XCTest
import Alamofire
import EVReflection

class issueTests: XCTestCase {
    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
        EVReflection.setBundleIdentifier(User)
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func testResponseObject() {
        let URL:URLStringConvertible = "http://XX-YOUR-DOMAIN-XX.com/api/v1/sites/?format=json"
        let expectation = expectationWithDescription("\(URL)")

        Alamofire.request(.GET, URL)
            .responseArray { (response: Result<[Site]>) in
                expectation.fulfill()

                if let result = response.value {
                    print("\(result.description)")

                    XCTAssertTrue(result.count > 10, "We should have at least 10 sites")

                }
        }
        waitForExpectationsWithTimeout(10, handler: { (error: NSError?) -> Void in
            XCTAssertNil(error, "\(error)")
        })
    }
}

class Site: EVObject {
    var id: Int = 0
    var recordId: String?
    var title: String?
    var nature: String?
    var latitude: Double = 0
    var longitude: Double = 0
    var startDate: NSDate?
    var endDate:NSDate?
    var nuisanceCar:Int = 0
    var nuisanceCarDescription: String?
    var nuisanceBike: Int = 0
    var nuisanceBikeDescription: String?
    var nuisancePedestrian: Int = 0
    var nuisancePedestrianDescription: String?
    var myfeelbackUrl: String?
}
dhanarajkawde commented 7 years ago

The class '_TtCC10Networking14ViewController13LogInResponse' is not key value coding-compliant for the key 'responseDesc' There is no support for optional type, array of optional or enum properties. As a workaround, you can implement the function 'setValue forUndefinedKey' for this. See the unit tests for more information

Please Help me in above error. Thanks

evermeer commented 7 years ago

@dhanarajkawde This could be multiple things. But first...

Both AlamofireJsonToObjects and AlamofireXmlToObjects are moved into EVReflection. You can use these by puting this in your podfile:

pod 'EVReflection/Alamofire'

There are now also sub specs for Moya, RxSwift and ReactiveSwift

Most common issues when you have this error are:

If you could both show me the LoginResponse class plus the json that you are trying to map, then that could help giving you the right answer.

dhanarajkawde commented 7 years ago

Thanks