Search code examples
iosswiftgraphqlapollojsonencoder

"Cannot convert value of type <Custom Scalar> to expected dictionary value type 'JSONEncodable?'" for Apollo iOS


I'm struggling with using "custom scalar" for my GraphQL Apollo iOS App.

I want to get "Timestamp" as "UInt64" so I followed solution written on Apollo Tutorial. Codeine to API.swift seems using Timestamp, which is custom scalar. But there's error in API.swift:

enter image description here

Cannot convert value of type 'Timestamp' (aka 'UInt64') to expected dictionary value type 'JSONEncodable?'

This is part of my API.swift including query:

public final class ScheduleListQuery: GraphQLQuery {
  /// The raw GraphQL definition of this operation.
  public let operationDefinition: String =
    """
    query ScheduleList($date: Timestamp!) {
      schedules(date: $date) {
        __typename
        schedules {
          __typename
          id
          name
          status
          category {
            __typename
            color
          }
          dateTimeStart
          dateTimeEnd
          stickerCount
          stickerNames
        }
      }
    }
    """

  public let operationName: String = "ScheduleList"

  public var date: Timestamp

  public init(date: Timestamp) {
    self.date = date
  }

  public var variables: GraphQLMap? {
    return ["date": date]
  }

...

This is my typealias Timestamp:

import Foundation
import Apollo

public typealias Timestamp = UInt64

extension Timestamp: JSONDecodable {

    public init(jsonValue value: JSONValue) throws {
        
        guard let string = value as? String else {
            throw JSONDecodingError.couldNotConvert(value: value, to: String.self)
        }
        
        guard let timeInterval = UInt64(string) else {
            throw JSONDecodingError.couldNotConvert(value: value, to: Double.self)
        }

        self = timeInterval
    }
}

Solution

  • To use custom scalar value as an argument you need to code Timestamp to conform to the JSONEncodable protocol too.

        
        public var jsonValue: JSONValue {
            return String(self)
        }
        
        public init(jsonValue value: JSONValue) throws {
            
            guard let string = value as? String else {
                throw JSONDecodingError.couldNotConvert(value: value, to: String.self)
            }
    
            guard let timestamp = Int64(string) else {
                throw JSONDecodingError.couldNotConvert(value: value, to: Date.self)
            }
    
            self = Int64(timestamp)
        }
        
    }
    

    Source: https://community.apollographql.com/t/cannot-convert-value-of-type-custom-scalar-to-expected-dictionary-value-type-jsonencodable-for-apollo-ios/4060