Closed PareshPatel721 closed 7 months ago
Hi @PareshPatel721 - since you mention the build phase script it sounds like you're familiar with the old 0.x versions. 1.0 has changed code generation quite a bit. We have a 1.0 migration guide and there is a specific section about custom scalars.
tl;dr - you need to write the custom scalar code yourself, just like before but in a different place now.
Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo iOS usage and allow us to serve you better.
I've written custom scalar code, but it still not working public typealias JSON = String (this is what i get default implementation)
In same file I've try to extend many ways like below
public typealias JSON = String
`extension JSON: JSONDecodable { public init(jsonValue value: JSONValue) throws { guard let dictionary = value as? Dictionary else { throw JSONDecodingError.couldNotConvert(value: value, to: Dictionary.self) }
self = dictionary
} }`
`extension SchemaConfiguration { public enum JSON: 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: JSON.self)
}
}
public var _jsonValue: JSONValue {
switch self {
case let .dictionary(json as AnyHashable),
let .array(json as AnyHashable):
return json
}
}
public static func == (lhs: JSON, rhs: JSON) -> Bool {
lhs._jsonValue == rhs._jsonValue
}
public func hash(into hasher: inout Hasher) {
hasher.combine(_jsonValue)
}
}
}`
`extension Schema { public enum JSON: 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: JSON.self)
}
}
public var _jsonValue: JSONValue {
switch self {
case let .dictionary(json as AnyHashable),
let .array(json as AnyHashable):
return json
}
}
public static func == (lhs: JSON, rhs: JSON) -> Bool {
lhs._jsonValue == rhs._jsonValue
}
public func hash(into hasher: inout Hasher) {
hasher.combine(_jsonValue)
}
}
}`
`extension JSON: JSONDecodable, JSONEncodable { public init(jsonValue value: JSONValue) throws {
let string = value as? String
if (string == nil) {
do {
let data1 = try JSONSerialization.data(withJSONObject: value, options: JSONSerialization.WritingOptions.prettyPrinted) // first of all convert json to the data
let convertedString = String(data: data1, encoding: String.Encoding.utf8) // the data will be converted to the string
if (convertedString == nil) {
throw JSONDecodingError.couldNotConvert(value: value, to: String.self)
} else {
self = convertedString ?? ""
}
} catch let myJSONError {
print(myJSONError)
throw JSONDecodingError.couldNotConvert(value: value, to: String.self)
}
} else {
self = string ?? ""
}
}
public var jsonValue: JSONValue {
return self
}
}`
` extension SchemaConfiguration { public enum JSON: 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: JSON.self)
}
}
public var _jsonValue: JSONValue {
switch self {
case let .dictionary(json as AnyHashable),
let .array(json as AnyHashable):
return json
}
}
public static func == (lhs: JSON, rhs: JSON) -> Bool {
lhs._jsonValue == rhs._jsonValue
}
public func hash(into hasher: inout Hasher) {
hasher.combine(_jsonValue)
}
}
} `
Please help me out where and how i can write custom scalar code, so my response get automatically parsed and confirmed to custom scalar
Thank you
Codegen is generating public typealias JSON = String
because that is the default for custom scalars in 1.0. We use String
because that is most likely the data type used to transport the data in the JSON payload and simple execution of the default generated operation model would succeed.
You are able to edit this file and the codegen engine will not overwrite it during the next code generation. So, if your custom scalar is not a String
then you must edit the code in that file and write the new code for your custom scalar. All this information can be found in our documentation on Custom Scalars.
Firstly you need to delete public typealias JSON = String
since your custom scalar is not String
.
Of the code you posted above this one looks correct but you might not need to put it inside an extension depending on how you created your schema module:
public enum JSON: 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: JSON.self)
}
}
public var _jsonValue: JSONValue {
switch self {
case
let .dictionary(json as AnyHashable),
let .array(json as AnyHashable):
return json
}
}
// You don't need to manually define `Equatable` and `Hashable` conformance the compiler will synthesize that for you.
}
@calvincestari That is working It saves my million of time Thank you for your time and effort
Question
I'm using Apollo 1.9.3 with local package support. So there are no any run script is needed to set in build phase. When i invoke My API from graphql server I'm getting error as ApolloAPI.JSONDecodingError.couldNotConvert(value: AnyHashable to: Swift.String
Local framework default generate JSON file in CustomScalar folder and file only contains public typealias JSON = String