watson-developer-cloud / swift-sdk

:iphone: The Watson Swift SDK enables developers to quickly add Watson Cognitive Computing services to their Swift applications.
https://watson-developer-cloud.github.io/swift-sdk/
Apache License 2.0
877 stars 223 forks source link

Cannot serialize Age model #485

Closed jaalger closed 7 years ago

jaalger commented 7 years ago

I am writing a Swift Visual Recognition application to mirror functionality of the Watson Web Demo:

http://visual-recognition-demo.mybluemix.net/

One of the APIs I am using is the visualRecognition.detectFaces in order to determine age, gender, celebrity match, etc. I am running into an issue where some photos do not include a min or max value for the face age. The issue here is that the min and max value for age are not optional values so I cannot even check if they exist and/or are nil.

Here is some simple recreation code:

visualRecognition.detectFaces(imageLocation, failure: visualRecongnitionDidFail){
            detectedFaces in
                for detectedFace in detectedFaces.images{
                    for face in detectedFace.faces{
                        print(face)
                    }
               }
        }

When an image is used that does not return a min or max age value the following error is seen:

Error Domain=com.alamofire.error Code=-6004 "Data could not be serialized. Failed to parse JSON response. The key (min) was not found in the JSON dictionary." UserInfo={NSLocalizedFailureReason=Data could not be serialized. Failed to parse JSON response. The key (min) was not found in the JSON dictionary.}

One of the images that causes this issue is the following:

https://upload.wikimedia.org/wikipedia/commons/thumb/7/7e/Thomas_J_Watson_Sr.jpg/1280px-Thomas_J_Watson_Sr.jpg

In Swift I attempt to do a nil check, but since the value is not optional Swift thinks it can never be nil:

 if(face.age.min != nil && face.age.max != nil){

              }

The compiler throws the following error: Value of type 'Int' can never be nil, comparison isn't allowed

In some of the other objects, such as face.identity? this is an optional value and I can check to make sure it is not nil.

This issue is blocking app development so I hope there is a workaround or solution soon.

jaalger commented 7 years ago

The same happens to many other objects as well. I have seen multiple required fields missing. Such as the following errors:

Error Domain=com.alamofire.error Code=-6004 "Data could not be serialized. Failed to parse JSON response. The key (classifiers) was not found in the JSON dictionary." UserInfo={NSLocalizedFailureReason=Data could not be serialized. Failed to parse JSON response. The key (classifiers) was not found in the JSON dictionary.}

Error Domain=com.alamofire.error Code=-6004 "Data could not be serialized. Failed to parse JSON response. The key (faces) was not found in the JSON dictionary." UserInfo={NSLocalizedFailureReason=Data could not be serialized. Failed to parse JSON response. The key (faces) was not found in the JSON dictionary.}

Again these are non optional fields and I cannot check to make sure they are returned. These errors are causing my app to crash since I cannot properly check for them since they are assumed to never be missing or nil

glennrfisher commented 7 years ago

Hi @jaalger. Unfortunately, we have some other issues that need to take priority right now. I'm not sure when we'll be able to tackle this, since we need to investigate the root cause. (Are these properties truly optional from the service? Is there an upstream issue that's preventing them from being returned? Has the returned model changed, preventing serialization?)

Since the SDK is open-source, feel free to fork it and investigate the issue further.

If you're interested, I would recommend starting by printing out the JSON response to the console. Here's an example of modifications to make, starting at VisualRecognition.swift line 618:

case .Success(let upload, _, _):
    upload.responseString { json in print(json) } // add this line to print the json payload
    upload.responseObject(dataToError: self.dataToError) {
        (response: Response<ImagesWithFaces, NSError>) in
        switch response.result {
        case .Success(let faceImages): success(faceImages)
        case .Failure(let error): failure?(error)
        }
    }

One idea, as you mentioned, would be to make the Age properties optional. But we'd want to double-check why they are optional when we thought they would be required.

sccheng commented 7 years ago

Hi @jaalger, sorry that it's taken so long, but I've started looking into this issue now. For the Age properties, it seems that the Visual Recognition service has certain age ranges (for example, a face can be classified as age 18-24). The lowest age range is essentially "17 and under" and the highest age range is "65 and over" - hence, there's no minimum for the lowest age range, and there's no maximum for the highest age range. Thanks for catching this - I think we'll plan to make the min and max fields optional.

As for the other errors, I was wondering if you could give me more information about which objects you're testing when you see the missing classifiers and faces fields. Thanks!

glennrfisher commented 7 years ago

Complete with Stephanie's PR, #530! :)