Skip to content

Commit 6b6fa1f

Browse files
lbalmacedahzalaz
authored andcommitted
Migrate Jackson usage to Gson (#26)
* replace jackson json parsing with gson * validate required fields exists when parsing json
1 parent 0a233c2 commit 6b6fa1f

19 files changed

Lines changed: 291 additions & 146 deletions

auth0/build.gradle

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ compileJava {
66

77
dependencies {
88
compile 'com.squareup.okhttp:okhttp:2.5.0'
9-
compile 'com.fasterxml.jackson.core:jackson-databind:2.4.1'
10-
compile 'com.fasterxml.jackson.core:jackson-core:2.4.1'
11-
compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.1'
9+
compile "com.google.code.gson:gson:2.6.2"
1210

1311
testCompile 'junit:junit:4.12'
1412
testCompile 'org.hamcrest:hamcrest-integration:1.3'

auth0/src/main/java/com/auth0/authentication/AuthenticationAPIClient.java

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@
2828
import com.auth0.authentication.result.Credentials;
2929
import com.auth0.authentication.result.DatabaseUser;
3030
import com.auth0.authentication.result.Delegation;
31+
import com.auth0.authentication.result.JsonRequiredTypeAdapterFactory;
3132
import com.auth0.authentication.result.UserProfile;
3233
import com.auth0.request.AuthenticationRequest;
3334
import com.auth0.request.ParameterizableRequest;
3435
import com.auth0.request.Request;
3536
import com.auth0.request.internal.RequestFactory;
3637
import com.auth0.util.Telemetry;
37-
import com.fasterxml.jackson.databind.ObjectMapper;
38+
import com.google.gson.Gson;
39+
import com.google.gson.GsonBuilder;
3840
import com.squareup.okhttp.HttpUrl;
3941
import com.squareup.okhttp.OkHttpClient;
4042

@@ -77,7 +79,7 @@ public class AuthenticationAPIClient {
7779

7880
private final Auth0 auth0;
7981
private final OkHttpClient client;
80-
private final ObjectMapper mapper;
82+
private final Gson gson;
8183
private final RequestFactory factory;
8284

8385
private String defaultDatabaseConnection = DEFAULT_DB_CONNECTION;
@@ -88,13 +90,13 @@ public class AuthenticationAPIClient {
8890
* @param auth0 account information
8991
*/
9092
public AuthenticationAPIClient(Auth0 auth0) {
91-
this(auth0, new OkHttpClient(), new ObjectMapper());
93+
this(auth0, new OkHttpClient(), buildGson());
9294
}
9395

94-
private AuthenticationAPIClient(Auth0 auth0, OkHttpClient client, ObjectMapper mapper) {
96+
private AuthenticationAPIClient(Auth0 auth0, OkHttpClient client, Gson gson) {
9597
this.auth0 = auth0;
9698
this.client = client;
97-
this.mapper = mapper;
99+
this.gson = gson;
98100
this.factory = new RequestFactory();
99101
final Telemetry telemetry = auth0.getTelemetry();
100102
if (telemetry != null) {
@@ -187,7 +189,7 @@ public AuthenticationRequest loginWithOAuthAccessToken(String token, String conn
187189
.setAccessToken(token)
188190
.asDictionary();
189191

190-
return factory.authenticationPOST(url, client, mapper)
192+
return factory.authenticationPOST(url, client, gson)
191193
.addAuthenticationParameters(parameters);
192194
}
193195

@@ -304,7 +306,7 @@ public DatabaseConnectionRequest<DatabaseUser> createUser(String email, String p
304306
.setConnection(defaultDatabaseConnection)
305307
.setClientId(getClientId())
306308
.asDictionary();
307-
final ParameterizableRequest<DatabaseUser> request = factory.POST(url, client, mapper, DatabaseUser.class)
309+
final ParameterizableRequest<DatabaseUser> request = factory.POST(url, client, gson, DatabaseUser.class)
308310
.addParameters(parameters);
309311
return new DatabaseConnectionRequest<>(request);
310312
}
@@ -413,7 +415,7 @@ public DatabaseConnectionRequest<Void> requestChangePassword(String email) {
413415
.setClientId(getClientId())
414416
.setConnection(defaultDatabaseConnection)
415417
.asDictionary();
416-
final ParameterizableRequest<Void> request = factory.POST(url, client, mapper)
418+
final ParameterizableRequest<Void> request = factory.POST(url, client, gson)
417419
.addParameters(parameters);
418420
return new DatabaseConnectionRequest<>(request);
419421
}
@@ -524,7 +526,7 @@ public Request<Void> unlink(String userId, String accessToken) {
524526
.set(USER_ID_KEY, userId)
525527
.asDictionary();
526528

527-
return factory.POST(url, client, mapper)
529+
return factory.POST(url, client, gson)
528530
.addParameters(parameters);
529531
}
530532

@@ -612,7 +614,7 @@ public ParameterizableRequest<Map<String, Object>> delegation() {
612614
.setClientId(getClientId())
613615
.setGrantType(ParameterBuilder.GRANT_TYPE_JWT)
614616
.asDictionary();
615-
return factory.rawPOST(url, client, mapper)
617+
return factory.rawPOST(url, client, gson)
616618
.addParameters(parameters);
617619
}
618620

@@ -626,7 +628,7 @@ protected <T> ParameterizableRequest<T> delegation(Class<T> clazz) {
626628
.setGrantType(ParameterBuilder.GRANT_TYPE_JWT)
627629
.asDictionary();
628630

629-
return factory.POST(url, client, mapper, clazz)
631+
return factory.POST(url, client, gson, clazz)
630632
.addParameters(parameters);
631633
}
632634

@@ -644,7 +646,7 @@ public ParameterizableRequest<Void> passwordless() {
644646
final Map<String, Object> parameters = ParameterBuilder.newBuilder()
645647
.setClientId(getClientId())
646648
.asDictionary();
647-
return factory.POST(url, client, mapper)
649+
return factory.POST(url, client, gson)
648650
.addParameters(parameters);
649651
}
650652

@@ -671,7 +673,7 @@ private AuthenticationRequest loginWithResourceOwner(Map<String, Object> paramet
671673
.setConnection(defaultDatabaseConnection)
672674
.addAll(parameters)
673675
.asDictionary();
674-
return factory.authenticationPOST(url, client, mapper)
676+
return factory.authenticationPOST(url, client, gson)
675677
.addAuthenticationParameters(requestParameters);
676678
}
677679

@@ -680,7 +682,7 @@ private ParameterizableRequest<UserProfile> profileRequest() {
680682
.addPathSegment(TOKEN_INFO_PATH)
681683
.build();
682684

683-
return factory.POST(url, client, mapper, UserProfile.class);
685+
return factory.POST(url, client, gson, UserProfile.class);
684686
}
685687

686688
/**
@@ -705,7 +707,13 @@ public AuthenticationRequest token(String authorizationCode, String codeVerifier
705707
.addPathSegment(TOKEN_PATH)
706708
.build();
707709

708-
return factory.authenticationPOST(url, client, mapper)
710+
return factory.authenticationPOST(url, client, gson)
709711
.addAuthenticationParameters(parameters);
710712
}
713+
714+
static Gson buildGson() {
715+
return new GsonBuilder()
716+
.registerTypeAdapterFactory(new JsonRequiredTypeAdapterFactory())
717+
.create();
718+
}
711719
}

auth0/src/main/java/com/auth0/authentication/result/Credentials.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,27 @@
2424

2525
package com.auth0.authentication.result;
2626

27-
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
28-
import com.fasterxml.jackson.annotation.JsonProperty;
27+
28+
import com.google.gson.annotations.SerializedName;
2929

3030
/**
3131
* Holds the user's credentials returned by Auth0.
3232
* <ul>
33-
* <li><i>idToken</i>: Identity Token with user information</li>
34-
* <li><i>accessToken</i>: Access Token for Auth0 API</li>
35-
* <li><i>refreshToken</i>: Refresh Token that can be used to request new tokens without signing in again</li>
33+
* <li><i>idToken</i>: Identity Token with user information</li>
34+
* <li><i>accessToken</i>: Access Token for Auth0 API</li>
35+
* <li><i>refreshToken</i>: Refresh Token that can be used to request new tokens without signing in again</li>
3636
* </ul>
3737
*/
38-
@JsonIgnoreProperties(ignoreUnknown = true)
3938
public class Credentials {
4039

40+
@SerializedName("id_token")
41+
@JsonRequired
4142
protected String idToken;
43+
@SerializedName("access_token")
4244
protected String accessToken;
45+
@SerializedName("token_type")
4346
protected String type;
47+
@SerializedName("refresh_token")
4448
protected String refreshToken;
4549

4650
protected Credentials(Credentials credentials) {
@@ -50,12 +54,10 @@ protected Credentials(Credentials credentials) {
5054
refreshToken = credentials.refreshToken;
5155
}
5256

53-
protected Credentials() { }
57+
protected Credentials() {
58+
}
5459

55-
public Credentials(@JsonProperty(value = "id_token", required = true) String idToken,
56-
@JsonProperty(value = "access_token") String accessToken,
57-
@JsonProperty(value = "token_type") String type,
58-
@JsonProperty(value = "refresh_token") String refreshToken) {
60+
public Credentials(String idToken, String accessToken, String type, String refreshToken) {
5961
this.idToken = idToken;
6062
this.accessToken = accessToken;
6163
this.type = type;

auth0/src/main/java/com/auth0/authentication/result/DatabaseUser.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,25 @@
2424

2525
package com.auth0.authentication.result;
2626

27-
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
28-
import com.fasterxml.jackson.annotation.JsonProperty;
27+
import com.google.gson.annotations.SerializedName;
2928

3029
/**
3130
* Auth0 user created in a Database connection.
3231
*
3332
* @see com.auth0.authentication.AuthenticationAPIClient#signUp(String, String)
3433
* @see com.auth0.authentication.AuthenticationAPIClient#signUp(String, String, String)
3534
*/
36-
@JsonIgnoreProperties(ignoreUnknown = true)
3735
public class DatabaseUser {
3836

37+
@SerializedName("email")
38+
@JsonRequired
3939
private final String email;
40+
@SerializedName("username")
4041
private final String username;
42+
@SerializedName("email_verified")
4143
private final boolean emailVerified;
4244

43-
public DatabaseUser(@JsonProperty(value = "email", required = true) String email,
44-
@JsonProperty("username") String username,
45-
@JsonProperty("email_verified") boolean emailVerified) {
45+
public DatabaseUser(String email, String username, boolean emailVerified) {
4646
this.email = email;
4747
this.username = username;
4848
this.emailVerified = emailVerified;

auth0/src/main/java/com/auth0/authentication/result/Delegation.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,23 @@
2424

2525
package com.auth0.authentication.result;
2626

27-
import com.fasterxml.jackson.annotation.JsonCreator;
28-
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
29-
import com.fasterxml.jackson.annotation.JsonProperty;
27+
import com.google.gson.annotations.SerializedName;
3028

3129
import static com.auth0.util.CheckHelper.checkArgument;
3230

3331
/**
3432
* The result of a successful delegation to an Auth0 application that contains a new Auth0 'id_token'
3533
* See <a href="https://auth0.com/docs/auth-api#!#post--delegation">delegation</a> docs
3634
*/
37-
@JsonIgnoreProperties(ignoreUnknown = true)
3835
public class Delegation {
36+
@SerializedName("id_token")
3937
private final String idToken;
38+
@SerializedName("token_type")
4039
private final String type;
40+
@SerializedName("expires_in")
4141
private final Long expiresIn;
4242

43-
@JsonCreator
44-
public Delegation(@JsonProperty(value = "id_token") String idToken,
45-
@JsonProperty(value = "token_type") String type,
46-
@JsonProperty(value = "expires_in") Long expiresIn) {
43+
public Delegation(String idToken, String type, Long expiresIn) {
4744
checkArgument(idToken != null, "id_token must be non-null");
4845
checkArgument(type != null, "token_type must be non-null");
4946
checkArgument(expiresIn != null, "expires_in must be non-null");
@@ -54,6 +51,7 @@ public Delegation(@JsonProperty(value = "id_token") String idToken,
5451

5552
/**
5653
* Identity Token
54+
*
5755
* @return the 'id_token' value
5856
*/
5957
public String getIdToken() {
@@ -62,6 +60,7 @@ public String getIdToken() {
6260

6361
/**
6462
* Token type
63+
*
6564
* @return the 'token_type' value
6665
*/
6766
public String getType() {
@@ -70,6 +69,7 @@ public String getType() {
7069

7170
/**
7271
* Token expire time in milliseconds since January 1, 1970, 00:00:00 GMT
72+
*
7373
* @return the 'expires_in' value
7474
*/
7575
public Long getExpiresIn() {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* JsonRequired.java
3+
*
4+
* Copyright (c) 2016 Auth0 (http://auth0.com)
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package com.auth0.authentication.result;
26+
27+
28+
import java.lang.annotation.ElementType;
29+
import java.lang.annotation.Retention;
30+
import java.lang.annotation.RetentionPolicy;
31+
import java.lang.annotation.Target;
32+
33+
34+
@Retention(RetentionPolicy.RUNTIME)
35+
@Target(ElementType.FIELD)
36+
public @interface JsonRequired {
37+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.auth0.authentication.result;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.JsonParseException;
5+
import com.google.gson.TypeAdapter;
6+
import com.google.gson.TypeAdapterFactory;
7+
import com.google.gson.reflect.TypeToken;
8+
import com.google.gson.stream.JsonReader;
9+
import com.google.gson.stream.JsonWriter;
10+
11+
import java.io.IOException;
12+
import java.lang.reflect.Field;
13+
14+
15+
public class JsonRequiredTypeAdapterFactory implements TypeAdapterFactory {
16+
17+
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
18+
19+
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
20+
21+
return new TypeAdapter<T>() {
22+
23+
public void write(JsonWriter out, T value) throws IOException {
24+
delegate.write(out, value);
25+
}
26+
27+
public T read(JsonReader in) throws IOException {
28+
T pojo = delegate.read(in);
29+
30+
Field[] fields = pojo.getClass().getDeclaredFields();
31+
for (Field f : fields) {
32+
if (f.getAnnotation(JsonRequired.class) != null) {
33+
try {
34+
f.setAccessible(true);
35+
if (f.get(pojo) == null) {
36+
throw new JsonParseException("Missing field in JSON: " + f.getName());
37+
}
38+
} catch (IllegalAccessException ex) {
39+
throw new JsonParseException("Missing field in JSON: " + f.getName(), ex);
40+
}
41+
}
42+
}
43+
return pojo;
44+
}
45+
}.nullSafe();
46+
}
47+
}

0 commit comments

Comments
 (0)