Last updated 1 min read

Apollo GraphQL: Using JSON Object as a Scalar Type

Related: iOS App Development, Software Engineering.


Sometimes, we have to deal with APIs that we don't have control over, and sometimes, they don't respect what GraphQL stands for type safety.

For example, an API returns a raw JSON object as a scalar type. By default, Apollo will likely attempt to parse as a String, which will fail.

Luckily Apollo allows us to work around it using a custom scalar type.

Custom JSON Object Scalar Type

Having a JSONObject scalar type in an API query definition we create a typealias for it:

public typealias JSONObject = CustomJSON

Then we implement CustomJSON scalar type:

  
public enum CustomJSON: CustomScalarType, Hashable {
    case dictionary([String: AnyHashable])
    case array([AnyHashable])
    
    public init(_jsonValue value: JSONValue) throws {
        if let dict = value as? [String: AnyHashable] {
            self = .dictionary(dict)
        } else if let array = value as? [AnyHashable] {
            self = .array(array)
        } else {
            throw JSONDecodingError.couldNotConvert(value: value, to: CustomJSON.self)
        }
    }
    
    public var _jsonValue: JSONValue {
        switch self {
        case let .dictionary(json as AnyHashable),
            let .array(json as AnyHashable):
            return json
        }
    }
    
    public static func <b> (lhs: CustomJSON, rhs: CustomJSON) -> Bool {
        lhs._jsonValue </b> rhs._jsonValue
    }
    
    public func hash(into hasher: inout Hasher) {
        hasher.combine(_jsonValue)
    }
}
 


References

Custom Scalars | Apollo GraphQL Docs