Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NetworkResponseExecutionSource.DataTransformer Returns nil When It Should Not #3034

Closed
asbhat opened this issue May 20, 2023 · 5 comments · Fixed by #3037
Closed

NetworkResponseExecutionSource.DataTransformer Returns nil When It Should Not #3034

asbhat opened this issue May 20, 2023 · 5 comments · Fixed by #3037
Assignees
Labels
bug Generally incorrect behavior

Comments

@asbhat
Copy link
Contributor

asbhat commented May 20, 2023

Summary

Using the subscript for the new ObjectData, which uses the NetworkResponseExecutionSource.DataTransformer, returns nil for integer id fields.

let value = object._rawData["id"]  // value is Optional(AnyHashable(<<Int>>))

switch value {
case let scalar as ScalarType:
  print(scalar)
case let customScalar as CustomScalarType:
  print(customScalar._jsonValue as? ScalarType)
default: print("nil!")  // prints "nil!"
}

switch value {
case let intID as Int: print(intID)  // this properly prints the int
default:
    print("\(type) could not translate \(value) from \(object)!!")
    return nil
}

Version

v1.2

Steps to reproduce the behavior

My project is closed, but the API I'm using (which I have no control over) is open.

URL: https://graphql.anilist.co

Example query

query MediaDetails($id: Int!) {
  Media(id: $id) {
    id
    updatedAt
  }
}

Schema Configuration

public enum SchemaConfiguration: ApolloAPI.SchemaConfiguration {
    public static func cacheKeyInfo(for type: ApolloAPI.Object, object: ApolloAPI.ObjectData) -> ApolloAPI.CacheKeyInfo? {
        switch type {
        case Objects.Media:
            let value = object._rawData["id"]  // value is Optional(AnyHashable(<<Int>>))

            switch value {
            case let scalar as ScalarType:
                print(scalar)
            case let customScalar as CustomScalarType:
                print(customScalar._jsonValue as? ScalarType)
            default: print("subscript returns nil")  // this line executes
            }

            switch value {
            case let intID as Int: 
                print(intID)  // this properly prints the int
                return CacheKeyInfo(id: String(intID))
            default:
                print("\(type) could not translate \(value) from \(object)!!")
                return nil
            }

        default: return nil
        }
    }
}

Logs

No response

Anything else?

https://anilist.github.io/ApiV2-GraphQL-Docs/

Let me know if there's anything else I can add to help!

@asbhat asbhat added bug Generally incorrect behavior needs investigation labels May 20, 2023
@BobaFetters
Copy link
Member

@asbhat Thanks for reporting this and providing the reproduction info! We will take a look at this as soon as we can.

@BobaFetters
Copy link
Member

The fix for this has been merged into main and will go out with our next release.

@asbhat For context, the issue was essentially the value in the _rawData being AnyHashable<Int64> instead of just Int due to how the JSONSerialization class works, so the ScalarType casting was failing. The subscript methods for ObjectData and ListData will now handle this appropriately, however directly accessing _rawData will still provide the Int64 value.

The recommended way to access values on ObjectData is through the subscript methods and not through the _rawData property which is meant for internal use. So this would be how you would access the data:

let value = object["id"]

@asbhat
Copy link
Contributor Author

asbhat commented May 23, 2023

Ahh ok thanks for the explanation and the fix!

I'll stop using the internal API once it gets released 🙂

@calvincestari
Copy link
Member

I'll stop using the internal API once it gets released 🙂

@asbhat the pattern we use to designate something is 'internal' is with the leading underscore _, or sometimes a double-underscore __. Because of the split between the Apollo and ApolloAPI modules we need to have types/functions public when they're only meant for internal use.

@asbhat
Copy link
Contributor Author

asbhat commented May 23, 2023

Ah yeah the underscore prefix is pretty standard. Thanks for clarifying!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Generally incorrect behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants