{"action":"created","comment":{"url":"https://api.github.com/repos/stripe/stripe-java/pulls/comments/85590584","pull_request_review_id":6298459,"id":85590584,"diff_hunk":"@@ -0,0 +1,45 @@\n+package com.stripe.model;\n+\n+import com.google.gson.*;\n+import java.lang.reflect.ParameterizedType;\n+import java.lang.reflect.Type;\n+\n+public class ExpandableFieldDeserializer implements JsonDeserializer<ExpandableField> {\n+    public ExpandableField deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {\n+        Gson gson = new GsonBuilder()\n+                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)\n+                .create();\n+\n+        if (json.isJsonNull()) {\n+            return null;\n+        }\n+\n+        ExpandableField expandableField;\n+\n+        // Check if json is a String ID:\n+        if (json.isJsonPrimitive()) {\n+            JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();\n+            if (jsonPrimitive.isString()) {\n+                expandableField = new ExpandableField(jsonPrimitive.getAsString(), null);\n+                return expandableField;\n+            }\n+            else {\n+                throw new JsonParseException(\"ExpandableField is a non-string primitive type.\");\n+            }\n+        }\n+        // Check if json is an expanded Object:\n+        else if (json.isJsonObject()) {\n+            // Get the `id` out of the response\n+            JsonObject fieldAsJsonObject = json.getAsJsonObject();\n+            String id = fieldAsJsonObject.getAsJsonPrimitive(\"id\").getAsString();\n+            // We need to get the type inside the generic ExpandableField to make sure fromJson correctly serializes\n+            // the JsonObject:\n+            Type clazz = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];\n+            expandableField = new ExpandableField(id, gson.fromJson(json, clazz));\n+            return expandableField;\n+        }\n+\n+        // If json is neither a String nor an Object, error:","path":"src/main/java/com/stripe/model/ExpandableFieldDeserializer.java","position":42,"original_position":42,"commit_id":"50cfb4ea6cfb7a46acf32c9204132cb96a0b9211","original_commit_id":"50cfb4ea6cfb7a46acf32c9204132cb96a0b9211","user":{"login":"brandur","id":96890,"avatar_url":"https://avatars.githubusercontent.com/u/96890?v=3","gravatar_id":"","url":"https://api.github.com/users/brandur","html_url":"https://github.com/brandur","followers_url":"https://api.github.com/users/brandur/followers","following_url":"https://api.github.com/users/brandur/following{/other_user}","gists_url":"https://api.github.com/users/brandur/gists{/gist_id}","starred_url":"https://api.github.com/users/brandur/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brandur/subscriptions","organizations_url":"https://api.github.com/users/brandur/orgs","repos_url":"https://api.github.com/users/brandur/repos","events_url":"https://api.github.com/users/brandur/events{/privacy}","received_events_url":"https://api.github.com/users/brandur/received_events","type":"User","site_admin":false},"body":"And maybe expand on this one with a \"We expect all expandable objects to fit the known string-or-object design. If one doesn't, then something may have changed in the API and this code may need to be updated.\"","created_at":"2016-10-28T18:55:35Z","updated_at":"2016-10-28T19:00:25Z","html_url":"https://github.com/stripe/stripe-java/pull/328#discussion_r85590584","pull_request_url":"https://api.github.com/repos/stripe/stripe-java/pulls/328","_links":{"self":{"href":"https://api.github.com/repos/stripe/stripe-java/pulls/comments/85590584"},"html":{"href":"https://github.com/stripe/stripe-java/pull/328#discussion_r85590584"},"pull_request":{"href":"https://api.github.com/repos/stripe/stripe-java/pulls/328"}}},"pull_request":{"url":"https://api.github.com/repos/stripe/stripe-java/pulls/328","id":91307865,"html_url":"https://github.com/stripe/stripe-java/pull/328","diff_url":"https://github.com/stripe/stripe-java/pull/328.diff","patch_url":"https://github.com/stripe/stripe-java/pull/328.patch","issue_url":"https://api.github.com/repos/stripe/stripe-java/issues/328","number":328,"state":"open","locked":false,"title":"Expandable Object Support,  Implement on Charge","user":{"login":"dpetrovics","id":288236,"avatar_url":"https://avatars.githubusercontent.com/u/288236?v=3","gravatar_id":"","url":"https://api.github.com/users/dpetrovics","html_url":"https://github.com/dpetrovics","followers_url":"https://api.github.com/users/dpetrovics/followers","following_url":"https://api.github.com/users/dpetrovics/following{/other_user}","gists_url":"https://api.github.com/users/dpetrovics/gists{/gist_id}","starred_url":"https://api.github.com/users/dpetrovics/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dpetrovics/subscriptions","organizations_url":"https://api.github.com/users/dpetrovics/orgs","repos_url":"https://api.github.com/users/dpetrovics/repos","events_url":"https://api.github.com/users/dpetrovics/events{/privacy}","received_events_url":"https://api.github.com/users/dpetrovics/received_events","type":"User","site_admin":false},"body":"This PR adds support for Expandable Objects and implements them for all expandable fields in the `Charge` class. We do this by creating a generic class `ExpandableField<T>`, that contains a String id and an object of type T. The primary advantage of this approach is that we're able to register just one new type adapter to deserialize any expanded object. This adapter, called `ExpandableFieldDeserializer` will return an `ExpandableField` that either:\r\n- is null if the json value is null\r\n- only has a String id and null `expandedObject` if the json value is a string JsonPrimitive\r\n- has both a String id and a properly typed `expandedObject` for expanded JsonObjects.\r\n\r\nCreating a generic deserializer was a bit awkward because of Java's type erasure. We have to perform some slightly magical runtime reflection in order to extract the correct class of the object to be expanded (if the json is an expanded object) so that it's properly deserialized.\r\n\r\nA couple other important design decisions:\r\n- We maintain backwards compatibility for all previous getters and setters for expandable fields. (These just get and set String IDs as before).\r\n- There is a new getter and setter for each expandable field, with the same name as before plus \"Object\" as the suffix. So, for example, for the `applicationFee` property on `Charge` we still support `getApplicationFee` and `setApplicationFee`, but now also have a `getApplicationFeeObject` and `setApplicationFeeObject`.\r\n- Because of the above bullet point, the `ExpandableField` generic class is pretty well encapsulated within the package - users should just use the previous accessors for String props and the new accessors for expanded props.\r\n\r\nTo use expansion in the api, just append to your params like so: `params.put(\"expand[]\", \"customer\")`. The default is still to not expand, as you'd expect.\r\n\r\nTesting:\r\n- Tests for deserializing a simple Charge with no expansions.\r\n- Tests for deserializing an (unrealistically) fully expanded Charge (sorry about the large .json file).\r\n- Getter/Setter tests for all expandable properties.\r\n-  A handful of functional tests for expanding properties on a Charge.\r\n- `ExpandableFieldDeserializer` tests for null, String, and Object json values.\r\n\r\nAddresses #268.\r\nr? @brandur ","created_at":"2016-10-28T01:13:04Z","updated_at":"2016-10-28T19:00:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ee0b95e794193a5ba94e9c2887a262ee8d73f753","assignee":{"login":"brandur","id":96890,"avatar_url":"https://avatars.githubusercontent.com/u/96890?v=3","gravatar_id":"","url":"https://api.github.com/users/brandur","html_url":"https://github.com/brandur","followers_url":"https://api.github.com/users/brandur/followers","following_url":"https://api.github.com/users/brandur/following{/other_user}","gists_url":"https://api.github.com/users/brandur/gists{/gist_id}","starred_url":"https://api.github.com/users/brandur/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brandur/subscriptions","organizations_url":"https://api.github.com/users/brandur/orgs","repos_url":"https://api.github.com/users/brandur/repos","events_url":"https://api.github.com/users/brandur/events{/privacy}","received_events_url":"https://api.github.com/users/brandur/received_events","type":"User","site_admin":false},"assignees":[{"login":"brandur","id":96890,"avatar_url":"https://avatars.githubusercontent.com/u/96890?v=3","gravatar_id":"","url":"https://api.github.com/users/brandur","html_url":"https://github.com/brandur","followers_url":"https://api.github.com/users/brandur/followers","following_url":"https://api.github.com/users/brandur/following{/other_user}","gists_url":"https://api.github.com/users/brandur/gists{/gist_id}","starred_url":"https://api.github.com/users/brandur/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brandur/subscriptions","organizations_url":"https://api.github.com/users/brandur/orgs","repos_url":"https://api.github.com/users/brandur/repos","events_url":"https://api.github.com/users/brandur/events{/privacy}","received_events_url":"https://api.github.com/users/brandur/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/stripe/stripe-java/pulls/328/commits","review_comments_url":"https://api.github.com/repos/stripe/stripe-java/pulls/328/comments","review_comment_url":"https://api.github.com/repos/stripe/stripe-java/pulls/comments{/number}","comments_url":"https://api.github.com/repos/stripe/stripe-java/issues/328/comments","statuses_url":"https://api.github.com/repos/stripe/stripe-java/statuses/50cfb4ea6cfb7a46acf32c9204132cb96a0b9211","head":{"label":"stripe:dpetrovics-expanding-objects","ref":"dpetrovics-expanding-objects","sha":"50cfb4ea6cfb7a46acf32c9204132cb96a0b9211","user":{"login":"stripe","id":856813,"avatar_url":"https://avatars.githubusercontent.com/u/856813?v=3","gravatar_id":"","url":"https://api.github.com/users/stripe","html_url":"https://github.com/stripe","followers_url":"https://api.github.com/users/stripe/followers","following_url":"https://api.github.com/users/stripe/following{/other_user}","gists_url":"https://api.github.com/users/stripe/gists{/gist_id}","starred_url":"https://api.github.com/users/stripe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stripe/subscriptions","organizations_url":"https://api.github.com/users/stripe/orgs","repos_url":"https://api.github.com/users/stripe/repos","events_url":"https://api.github.com/users/stripe/events{/privacy}","received_events_url":"https://api.github.com/users/stripe/received_events","type":"Organization","site_admin":false},"repo":{"id":2176646,"name":"stripe-java","full_name":"stripe/stripe-java","owner":{"login":"stripe","id":856813,"avatar_url":"https://avatars.githubusercontent.com/u/856813?v=3","gravatar_id":"","url":"https://api.github.com/users/stripe","html_url":"https://github.com/stripe","followers_url":"https://api.github.com/users/stripe/followers","following_url":"https://api.github.com/users/stripe/following{/other_user}","gists_url":"https://api.github.com/users/stripe/gists{/gist_id}","starred_url":"https://api.github.com/users/stripe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stripe/subscriptions","organizations_url":"https://api.github.com/users/stripe/orgs","repos_url":"https://api.github.com/users/stripe/repos","events_url":"https://api.github.com/users/stripe/events{/privacy}","received_events_url":"https://api.github.com/users/stripe/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/stripe/stripe-java","description":"Stripe Java bindings","fork":false,"url":"https://api.github.com/repos/stripe/stripe-java","forks_url":"https://api.github.com/repos/stripe/stripe-java/forks","keys_url":"https://api.github.com/repos/stripe/stripe-java/keys{/key_id}","collaborators_url":"https://api.github.com/repos/stripe/stripe-java/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/stripe/stripe-java/teams","hooks_url":"https://api.github.com/repos/stripe/stripe-java/hooks","issue_events_url":"https://api.github.com/repos/stripe/stripe-java/issues/events{/number}","events_url":"https://api.github.com/repos/stripe/stripe-java/events","assignees_url":"https://api.github.com/repos/stripe/stripe-java/assignees{/user}","branches_url":"https://api.github.com/repos/stripe/stripe-java/branches{/branch}","tags_url":"https://api.github.com/repos/stripe/stripe-java/tags","blobs_url":"https://api.github.com/repos/stripe/stripe-java/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/stripe/stripe-java/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/stripe/stripe-java/git/refs{/sha}","trees_url":"https://api.github.com/repos/stripe/stripe-java/git/trees{/sha}","statuses_url":"https://api.github.com/repos/stripe/stripe-java/statuses/{sha}","languages_url":"https://api.github.com/repos/stripe/stripe-java/languages","stargazers_url":"https://api.github.com/repos/stripe/stripe-java/stargazers","contributors_url":"https://api.github.com/repos/stripe/stripe-java/contributors","subscribers_url":"https://api.github.com/repos/stripe/stripe-java/subscribers","subscription_url":"https://api.github.com/repos/stripe/stripe-java/subscription","commits_url":"https://api.github.com/repos/stripe/stripe-java/commits{/sha}","git_commits_url":"https://api.github.com/repos/stripe/stripe-java/git/commits{/sha}","comments_url":"https://api.github.com/repos/stripe/stripe-java/comments{/number}","issue_comment_url":"https://api.github.com/repos/stripe/stripe-java/issues/comments{/number}","contents_url":"https://api.github.com/repos/stripe/stripe-java/contents/{+path}","compare_url":"https://api.github.com/repos/stripe/stripe-java/compare/{base}...{head}","merges_url":"https://api.github.com/repos/stripe/stripe-java/merges","archive_url":"https://api.github.com/repos/stripe/stripe-java/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/stripe/stripe-java/downloads","issues_url":"https://api.github.com/repos/stripe/stripe-java/issues{/number}","pulls_url":"https://api.github.com/repos/stripe/stripe-java/pulls{/number}","milestones_url":"https://api.github.com/repos/stripe/stripe-java/milestones{/number}","notifications_url":"https://api.github.com/repos/stripe/stripe-java/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/stripe/stripe-java/labels{/name}","releases_url":"https://api.github.com/repos/stripe/stripe-java/releases{/id}","deployments_url":"https://api.github.com/repos/stripe/stripe-java/deployments","created_at":"2011-08-09T00:06:31Z","updated_at":"2016-10-27T13:53:30Z","pushed_at":"2016-10-28T01:13:04Z","git_url":"git://github.com/stripe/stripe-java.git","ssh_url":"git@github.com:stripe/stripe-java.git","clone_url":"https://github.com/stripe/stripe-java.git","svn_url":"https://github.com/stripe/stripe-java","homepage":"https://stripe.com","size":1800,"stargazers_count":209,"watchers_count":209,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":143,"mirror_url":null,"open_issues_count":13,"forks":143,"open_issues":13,"watchers":209,"default_branch":"master"}},"base":{"label":"stripe:master","ref":"master","sha":"c8a6f1463aa6fb339efaa89ef38701ea982bccca","user":{"login":"stripe","id":856813,"avatar_url":"https://avatars.githubusercontent.com/u/856813?v=3","gravatar_id":"","url":"https://api.github.com/users/stripe","html_url":"https://github.com/stripe","followers_url":"https://api.github.com/users/stripe/followers","following_url":"https://api.github.com/users/stripe/following{/other_user}","gists_url":"https://api.github.com/users/stripe/gists{/gist_id}","starred_url":"https://api.github.com/users/stripe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stripe/subscriptions","organizations_url":"https://api.github.com/users/stripe/orgs","repos_url":"https://api.github.com/users/stripe/repos","events_url":"https://api.github.com/users/stripe/events{/privacy}","received_events_url":"https://api.github.com/users/stripe/received_events","type":"Organization","site_admin":false},"repo":{"id":2176646,"name":"stripe-java","full_name":"stripe/stripe-java","owner":{"login":"stripe","id":856813,"avatar_url":"https://avatars.githubusercontent.com/u/856813?v=3","gravatar_id":"","url":"https://api.github.com/users/stripe","html_url":"https://github.com/stripe","followers_url":"https://api.github.com/users/stripe/followers","following_url":"https://api.github.com/users/stripe/following{/other_user}","gists_url":"https://api.github.com/users/stripe/gists{/gist_id}","starred_url":"https://api.github.com/users/stripe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stripe/subscriptions","organizations_url":"https://api.github.com/users/stripe/orgs","repos_url":"https://api.github.com/users/stripe/repos","events_url":"https://api.github.com/users/stripe/events{/privacy}","received_events_url":"https://api.github.com/users/stripe/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/stripe/stripe-java","description":"Stripe Java bindings","fork":false,"url":"https://api.github.com/repos/stripe/stripe-java","forks_url":"https://api.github.com/repos/stripe/stripe-java/forks","keys_url":"https://api.github.com/repos/stripe/stripe-java/keys{/key_id}","collaborators_url":"https://api.github.com/repos/stripe/stripe-java/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/stripe/stripe-java/teams","hooks_url":"https://api.github.com/repos/stripe/stripe-java/hooks","issue_events_url":"https://api.github.com/repos/stripe/stripe-java/issues/events{/number}","events_url":"https://api.github.com/repos/stripe/stripe-java/events","assignees_url":"https://api.github.com/repos/stripe/stripe-java/assignees{/user}","branches_url":"https://api.github.com/repos/stripe/stripe-java/branches{/branch}","tags_url":"https://api.github.com/repos/stripe/stripe-java/tags","blobs_url":"https://api.github.com/repos/stripe/stripe-java/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/stripe/stripe-java/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/stripe/stripe-java/git/refs{/sha}","trees_url":"https://api.github.com/repos/stripe/stripe-java/git/trees{/sha}","statuses_url":"https://api.github.com/repos/stripe/stripe-java/statuses/{sha}","languages_url":"https://api.github.com/repos/stripe/stripe-java/languages","stargazers_url":"https://api.github.com/repos/stripe/stripe-java/stargazers","contributors_url":"https://api.github.com/repos/stripe/stripe-java/contributors","subscribers_url":"https://api.github.com/repos/stripe/stripe-java/subscribers","subscription_url":"https://api.github.com/repos/stripe/stripe-java/subscription","commits_url":"https://api.github.com/repos/stripe/stripe-java/commits{/sha}","git_commits_url":"https://api.github.com/repos/stripe/stripe-java/git/commits{/sha}","comments_url":"https://api.github.com/repos/stripe/stripe-java/comments{/number}","issue_comment_url":"https://api.github.com/repos/stripe/stripe-java/issues/comments{/number}","contents_url":"https://api.github.com/repos/stripe/stripe-java/contents/{+path}","compare_url":"https://api.github.com/repos/stripe/stripe-java/compare/{base}...{head}","merges_url":"https://api.github.com/repos/stripe/stripe-java/merges","archive_url":"https://api.github.com/repos/stripe/stripe-java/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/stripe/stripe-java/downloads","issues_url":"https://api.github.com/repos/stripe/stripe-java/issues{/number}","pulls_url":"https://api.github.com/repos/stripe/stripe-java/pulls{/number}","milestones_url":"https://api.github.com/repos/stripe/stripe-java/milestones{/number}","notifications_url":"https://api.github.com/repos/stripe/stripe-java/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/stripe/stripe-java/labels{/name}","releases_url":"https://api.github.com/repos/stripe/stripe-java/releases{/id}","deployments_url":"https://api.github.com/repos/stripe/stripe-java/deployments","created_at":"2011-08-09T00:06:31Z","updated_at":"2016-10-27T13:53:30Z","pushed_at":"2016-10-28T01:13:04Z","git_url":"git://github.com/stripe/stripe-java.git","ssh_url":"git@github.com:stripe/stripe-java.git","clone_url":"https://github.com/stripe/stripe-java.git","svn_url":"https://github.com/stripe/stripe-java","homepage":"https://stripe.com","size":1800,"stargazers_count":209,"watchers_count":209,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":143,"mirror_url":null,"open_issues_count":13,"forks":143,"open_issues":13,"watchers":209,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/stripe/stripe-java/pulls/328"},"html":{"href":"https://github.com/stripe/stripe-java/pull/328"},"issue":{"href":"https://api.github.com/repos/stripe/stripe-java/issues/328"},"comments":{"href":"https://api.github.com/repos/stripe/stripe-java/issues/328/comments"},"review_comments":{"href":"https://api.github.com/repos/stripe/stripe-java/pulls/328/comments"},"review_comment":{"href":"https://api.github.com/repos/stripe/stripe-java/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/stripe/stripe-java/pulls/328/commits"},"statuses":{"href":"https://api.github.com/repos/stripe/stripe-java/statuses/50cfb4ea6cfb7a46acf32c9204132cb96a0b9211"}}}}
{"actor":{"display_login":"brandur"}}