SwiftGraphQL by default encodes all fields that reference unconfigured scalars as AnyCodable
values. For easier decoding and better type support you can, however, create custom GraphQLScalar
structures.
To create a custom scalar, you need to create a structure that conforms to the GraphQLScalar
protocol.
public protocol GraphQLScalar: Encodable {
init(from: AnyCodable) throws
static var mockValue: Self { get }
}
It doesn’t matter where you implement the conformance as long as it’s in the same project as the generated code.
Because GraphQLScalar
uses the Encodable
protocol to encode the value, you might need to customize how JSONEncoder
encodes the built-in value in case you are mapping a custom scalar to a built-in type. Depending on your target, you should either
- pass a custom
JSONEncoder
as a paramater to the URLRequest.query
method,
- provide a custom
encoder
to FetchExchange
- modify the
encoder
in GraphQLWebSocketConfiguration
.
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
let request = URLRequest(url: API_ENDPOINT)
request.query(selection, encoder: encoder)
let client = SwiftGraphQLClient.Client(
request: API_ENDPOINT,
exchanges: [
FetchExchange(encoder: encoder)
]
)
let config = GraphQLWebSocketConfiguration()
config.encoder = encoder
let ws = GraphQLWebSocket(request: request, config: config)
Example DateTime Scalar
import Foundation
import GraphQL
import SwiftGraphQL
extension Date: GraphQLScalar {
public init(from codable: AnyCodable) throws {
guard let raw = codable.value as? String else {
throw DateTimeScalarDecodingError.invalidType
}
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
guard let date = formatter.date(from: raw) else {
throw DateTimeScalarDecodingError.invalidValue
}
self = date
}
public static var mockValue = Date.now
}
enum DateTimeScalarDecodingError: Error {
case invalidType
case invalidValue
}
Don’t forget to add your scalar mapping to code generator options!