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

How to define the rules for type convert #94

Closed
jzhw0130 opened this issue Jun 6, 2017 · 9 comments · Fixed by #1474
Closed

How to define the rules for type convert #94

jzhw0130 opened this issue Jun 6, 2017 · 9 comments · Fixed by #1474
Labels
codegen Issues related to or arising from code generation docs Focuses on documentation changes

Comments

@jzhw0130
Copy link

jzhw0130 commented Jun 6, 2017

@martijnwalraven

Server define a type 'Date', the format is '2017-06-06' or 1496736244000, (string or int).
Generate the scheme.json by apollo-codegen download-schema, the type is 'Date', too

Generate the API.swift by apollo-codegen generate , the type convert to 'String' automatically. Then data decode will throw exception when server format is int(1496736244000). Because it can not convert 'Int' to 'String'..

Now I have to change the API.swift manually, from 'String' to 'Int'. But it is not good, I have to do it many times when scheme changes...

Could you tell me the best way to solve the problem?

Thanks a lot

Jing

@cerupcat
Copy link

cerupcat commented Sep 5, 2017

Did you find a solution for this? I'm also looking how to automatically create Date types during apollo codegen.

@martijnwalraven
Copy link
Contributor

@cerupcat @jzhw0130: You should be able to pass --passthrough-custom-scalars to apollo-codegen to avoid generating a typealias to String for custom scalars. You can then add your own alias and conversion code, see here for an example.

@cerupcat
Copy link

cerupcat commented Sep 5, 2017

Awesome, thanks! Will take a look.

@jzhw0130
Copy link
Author

jzhw0130 commented Sep 7, 2017

@cerupcat I just modify the scheme.json manually to solve the problem

@cerupcat
Copy link

cerupcat commented Sep 7, 2017

Thanks @jzhw0130. I don't think that would work for us since we share the schema file across platforms and it gets auto generated when we make changes. Will be giving the other solution a try when we get back to that part.

@shehang
Copy link

shehang commented Dec 13, 2017

@jzhw0130 & @cerupcat Do you guys found a way to solve this?
I tried modifying the scheme.json file but it doesn't work.
Having trouble Decoding & Encoding DateTime type to Date in typealias.

Any help is appreciated.

@rickycpadilla
Copy link

I ran into a similar issue today and was able to find a solution.

Our schema had a custom scalar called Date. I wasn't able to make a type alias because Swift already obviously has type Date - plus, I wanted to convert the schema Date to Swift Date anyhow.

Here's what I did:

  1. Add --passthroughCustomScalars to the build phase like below (see last line):
APOLLO_FRAMEWORK_PATH="$(eval find $FRAMEWORK_SEARCH_PATHS -name "Apollo.framework" -maxdepth 1)"

if [ -z "$APOLLO_FRAMEWORK_PATH" ]; then
echo "error: Couldn't find Apollo.framework in FRAMEWORK_SEARCH_PATHS; make sure to add the framework to your project."
exit 1
fi

cd "${SRCROOT}/${TARGET_NAME}"
$APOLLO_FRAMEWORK_PATH/check-and-run-apollo-cli.sh codegen:generate --queries="$(find . -name '*.graphql')" --passthroughCustomScalars --schema=schema.json API.swift
  1. Add a Date extension like:
import Apollo

extension Date: JSONDecodable {
  public init(jsonValue value: JSONValue) throws {
    guard let isoString = value as? String else {
      throw JSONDecodingError.couldNotConvert(value: value, to: Date.self)
    }
    let formatter = ISO8601DateFormatter()
    formatter.formatOptions = [.withFractionalSeconds]
    guard let date = formatter.date(from: isoString) else {
      throw JSONDecodingError.couldNotConvert(value: value, to: Date.self)
    }
    self = date
  }
}

NOTE: Depending on the format of your ISO date string, you'll likely need to change formatter.formatOptions = [.withFractionalSeconds]. Our date strings have milliseconds, so I had to add these options for this to work.

@RolandasRazma
Copy link
Contributor

RolandasRazma commented Jan 11, 2019

Seeing people struggling with this, thought I will add my experience.
We have similar like @jzhw0130
Date format is '2017-06-06'
DateTime format is '2017-01-23T10:12:31Z' // ISO8601
Seconds format of 1496736244000 // Unix time stamp
and many other meaningless type like Markdown, VIDEO_ID etc that coming in string type

what we do is:

a) bash script to download and "transform" schema (with some comments):

# download new schema
apollo schema:download $SCHEMA_PATH --endpoint=$ENDPOINT_PATH

# strip down types we can't handle by representing them as strings 
# (they are represented as strings in JSON)
perl -i -0pe 's/("kind":\s*"SCALAR",\s*"name":\s*")(Date|Markdown|VIDEO_ID)(")/\1String\3/gms' $SCHEMA_PATH

# Unix timestamp (Seconds) is represented as "TimeInterval" in iOS 
# (in similar fashion you can "converting" your "Date" to "DateNoTime" if you want it to be typed in Swift)
perl -i -0pe 's/("kind":\s*"SCALAR",\s*"name":\s*")(Seconds)(")/\1TimeInterval\3/gms' $SCHEMA_PATH

b) Types.swift (in project)

public typealias DateTime = Date

extension DateTime: JSONDecodable, JSONEncodable {
    
    public init(jsonValue value: JSONValue) throws {
        guard let string = value as? String else {
            throw JSONDecodingError.couldNotConvert(value: value, to: String.self)
        }

        guard let date = ISO8601DateFormatter().date(from: string) else {
            throw JSONDecodingError.couldNotConvert(value: value, to: Date.self)
        }
        
        self = date
    }
    
    public var jsonValue: JSONValue {
        return ISO8601DateTimeFormatter.string(from: self)
    }
    
}

what this setup gives us is:
Date will be "String"
DateTime will be Swift "Date" (alias, decoded with our extension)
Seconds will be "TimeInterval" (decoded without any extension)

@designatednerd
Copy link
Contributor

I've (finally) added some actual documentation and an example for this with #1474 - would appreciate any feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
codegen Issues related to or arising from code generation docs Focuses on documentation changes
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants