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

Properly deserialize source on BT during expand #1165

Merged
merged 1 commit into from
Jul 23, 2018

Conversation

remi-stripe
Copy link
Contributor

@remi-stripe remi-stripe commented Apr 23, 2018

This PR adds support for deserializing source on a Balance Transaction properly. It used to map to a Source class which is a "parent class" for payment methods and has nothing to do with balance transaction.

There's a new custom deserializer and type for this that looks at the balance transaction's source object property and deserializes the right type based on this.

This PR also adds support for local JSON files as fixtures for the new test suite to properly test deserializing all source types.

Fixes #1162
cc @stripe/api-libraries

@remi-stripe
Copy link
Contributor Author

remi-stripe commented Apr 23, 2018

@ob-stripe Can you have a quick look and confirm this is the right direction? Some questions

  • How can I handle testing this? Should I create BTs for each type and confirm they get deserialized properly on expand like I do in the Charge one?
  • How can I handle deserializing new types into a generic StripeObject? StripeEntityWithId is abstract so I could create a new type that would be StripeObject that inherits from it but not sure it's the right direction. The goal would be to be able to access the raw JSON if you want things on types we have not yet added to stripe-dotnet (or older versions of the lib). For now I set the type to Unknown.
  • I modeled this on the Source.cs implementation. C# does not seem to have union support but is this the best approach?

@remi-stripe remi-stripe force-pushed the remi-add-bt-source-deserialization branch from 851a0cc to adb8321 Compare April 23, 2018 13:22
@ob-stripe
Copy link
Contributor

This looks mostly on the right track to me. Thanks for taking a stab at this @remi-stripe!

How can I handle testing this? Should I create BTs for each type and confirm they get deserialized properly on expand like I do in the Charge one?

Ugh. I'd rather avoid adding complex tests that use the real API. The test suite already takes forever to run, and these tests will either be painful to port to stripe-mock or will be scraped entirely. Since it's unlikely stripe-mock will support returning different source objects under balance_transaction in the near future, I suppose the right thing to do would be to test the various cases using a local set of JSON fixtures, but right now stripe-dotnet does not support stubbing requests...

@brandur-stripe Any thoughts here?

How can I handle deserializing new types into a generic StripeObject? StripeEntityWithId is abstract so I could create a new type that would be StripeObject that inherits from it but not sure it's the right direction. The goal would be to be able to access the raw JSON if you want things on types we have not yet added to stripe-dotnet (or older versions of the lib). For now I set the type to Unknown.

Honestly, I'd rather throw an exception with a message saying to contact support so we can update the library with missing types. Just returning the raw JSON does not sound like a great developer experience. I understand that updating stripe-dotnet can be painful because of the pinned API version and semi-frequent major version bumps, but I don't think we're going to add new types often enough that we should have an escape hatch specifically for this case.

(Worst case, the JSON of the entire response is always accessible via the StripeResponse object.)

I modeled this on the Source.cs implementation. C# does not seem to have union support but is this the best approach?

Not a C# expert™, but that seems fine to me. C unions are not really compatible with classes anyway (even in C++, you cannot have any kind of virtual functions in a union).

@remi-stripe
Copy link
Contributor Author

Honestly, I'd rather throw an exception with a message saying to contact support so we can update the library with missing types. Just returning the raw JSON does not sound like a great developer experience. I understand that updating stripe-dotnet can be painful because of the pinned API version and semi-frequent major version bumps, but I don't think we're going to add new types often enough that we should have an escape hatch specifically for this case.

We can not do that. If we did this it'd mean that as soon as we add a new type, anyone could end up with an exception or a crash in their production application right? New types are not a breaking change and could be introduced.
I'm fine leaving as is without a custom type but at least putting Unknown as the enum value so that you can do a case on it in the code and look into it as a developer.

@ob-stripe
Copy link
Contributor

If we did this it'd mean that as soon as we add a new type, anyone could end up with an exception or a crash in their production application right?

Ah, good point. Sigh, who decided that an expandable polymorphic attribute was a good idea anyway :shakes_fist:

So yeah, Type=Unknown sounds good to me then.

@jaymedavis
Copy link
Contributor

@remi-stripe
Copy link
Contributor Author

@jaymedavis Yeah I looked into it but it seems a bit hacky/complex for the sake of saving a little bit of memory

@jaymedavis
Copy link
Contributor

Thought that might be the case. To my knowledge, .net developers rarely ever use the struct keyword anyway.

@remi-stripe remi-stripe force-pushed the remi-add-bt-source-deserialization branch from adb8321 to 74848d9 Compare July 22, 2018 23:08
@remi-stripe remi-stripe changed the title [WIP] Properly deserialize source on BT during expand Properly deserialize source on BT during expand Jul 22, 2018
@remi-stripe
Copy link
Contributor Author

@ob-stripe I took another stab at this PR now that I better understand the test suite based on stripe-mock. Can you have a look as I think it's ready to merge.

It's a breaking change, but also it never worked so not sure what we want to do here?

@remi-stripe remi-stripe force-pushed the remi-add-bt-source-deserialization branch from 74848d9 to 49ce8af Compare July 23, 2018 12:16
Copy link
Contributor

@ob-stripe ob-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a minor comment, but looks great otherwise.

// works as expectes.
var json = GetResourceAsString("api_fixtures.balance_transaction_with_expansion.json");
var balanceTransactions = Mapper<StripeList<StripeBalanceTransaction>>.MapFromJson(json);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just add a couple of asserts here:

Assert.NotNull(balanceTransactions.Data)
Assert.IsTrue(balanceTransactions.Data.Count >= 9)

just to avoid exceptions when trying to access something that doesn't exist if the deserialization goes wrong (or if something is wrong with the fixture itself).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ob-stripe done! PTAL

@ob-stripe
Copy link
Contributor

It's a breaking change, but also it never worked so not sure what we want to do here?

I think it's fine to release this as a minor version. Technically, the API changed, but as you pointed out no integration could use the previous API anyway, so in practice it's more like a new feature.

@remi-stripe remi-stripe force-pushed the remi-add-bt-source-deserialization branch from 49ce8af to 8eb8d8e Compare July 23, 2018 12:41
@ob-stripe ob-stripe merged commit 4c9ef51 into master Jul 23, 2018
@ob-stripe ob-stripe deleted the remi-add-bt-source-deserialization branch July 23, 2018 14:16
@ob-stripe
Copy link
Contributor

Released as 17.4.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

StripeBalanceTransaction has incorrect Source type
3 participants