Ensured JJWT's org.json use is compatible with Android's org.json API as defined in https://developer.android.com/reference/org/json/package-summary. Resolves #380.

This commit is contained in:
Les Hazlewood 2018-08-07 13:29:55 -04:00
parent 5e5f29d8b1
commit f19c34a763
10 changed files with 51 additions and 23 deletions

View File

@ -1,5 +1,11 @@
## Release Notes ## Release Notes
### 0.10.2
This is a minor patch release that ensures the `OrgJsonSerializer` and `OrgJsonDeserializer` implementations are
compatible with Android's older `org.json` API. Previously JJWT used newer `org.json` APIs that are not
available on Android.
### 0.10.1 ### 0.10.1
This is a minor point release that ensures the BouncyCastle dependency is optional and not pulled in as a transitive This is a minor point release that ensures the BouncyCastle dependency is optional and not pulled in as a transitive

View File

@ -179,18 +179,18 @@ If you're building a (non-Android) JDK project, you will want to define the foll
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId> <artifactId>jjwt-api</artifactId>
<version>0.10.1</version> <version>0.10.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId> <artifactId>jjwt-impl</artifactId>
<version>0.10.1</version> <version>0.10.2</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <artifactId>jjwt-jackson</artifactId>
<version>0.10.1</version> <version>0.10.2</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<!-- Uncomment this next dependency if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms: <!-- Uncomment this next dependency if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms:
@ -209,11 +209,11 @@ If you're building a (non-Android) JDK project, you will want to define the foll
```groovy ```groovy
dependencies { dependencies {
compile 'io.jsonwebtoken:jjwt-api:0.10.1' compile 'io.jsonwebtoken:jjwt-api:0.10.2'
runtime 'io.jsonwebtoken:jjwt-impl:0.10.1', runtime 'io.jsonwebtoken:jjwt-impl:0.10.2',
// Uncomment the next line if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms: // Uncomment the next line if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms:
//'org.bouncycastle:bcprov-jdk15on:1.60', //'org.bouncycastle:bcprov-jdk15on:1.60',
'io.jsonwebtoken:jjwt-jackson:0.10.1' 'io.jsonwebtoken:jjwt-jackson:0.10.2'
} }
``` ```
@ -229,9 +229,9 @@ Add the dependencies to your project:
```groovy ```groovy
dependencies { dependencies {
compile 'io.jsonwebtoken:jjwt-api:0.10.1' compile 'io.jsonwebtoken:jjwt-api:0.10.2'
runtime 'io.jsonwebtoken:jjwt-impl:0.10.1' runtime 'io.jsonwebtoken:jjwt-impl:0.10.2'
runtime('io.jsonwebtoken:jjwt-orgjson:0.10.1') { runtime('io.jsonwebtoken:jjwt-orgjson:0.10.2') {
exclude group: 'org.json', module: 'json' //provided by Android natively exclude group: 'org.json', module: 'json' //provided by Android natively
} }
// Uncomment the next line if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms: // Uncomment the next line if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms:
@ -1192,7 +1192,7 @@ scope which is the typical JJWT default). That is:
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <artifactId>jjwt-jackson</artifactId>
<version>0.10.1</version> <version>0.10.2</version>
<scope>compile</scope> <!-- Not runtime --> <scope>compile</scope> <!-- Not runtime -->
</dependency> </dependency>
``` ```
@ -1201,7 +1201,7 @@ scope which is the typical JJWT default). That is:
```groovy ```groovy
dependencies { dependencies {
compile 'io.jsonwebtoken:jjwt-jackson:0.10.1' compile 'io.jsonwebtoken:jjwt-jackson:0.10.2'
} }
``` ```

View File

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId> <artifactId>jjwt-root</artifactId>
<version>0.10.1</version> <version>0.10.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId> <artifactId>jjwt-root</artifactId>
<version>0.10.1</version> <version>0.10.2-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

View File

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId> <artifactId>jjwt-root</artifactId>
<version>0.10.1</version> <version>0.10.2-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

View File

@ -8,6 +8,7 @@ import org.json.JSONObject;
import org.json.JSONTokener; import org.json.JSONTokener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -46,7 +47,7 @@ public class OrgJsonDeserializer implements Deserializer<Object> {
if (c == '{') { //json object if (c == '{') { //json object
JSONObject o = new JSONObject(tokener); JSONObject o = new JSONObject(tokener);
return toMap(o); return toMap(o);
} else if ( c == '[' ) { } else if (c == '[') {
JSONArray a = new JSONArray(tokener); JSONArray a = new JSONArray(tokener);
return toList(a); return toList(a);
} else { } else {
@ -58,7 +59,10 @@ public class OrgJsonDeserializer implements Deserializer<Object> {
private Map<String, Object> toMap(JSONObject o) { private Map<String, Object> toMap(JSONObject o) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
for (String key : o.keySet()) { // https://github.com/jwtk/jjwt/issues/380: use .keys() and *not* .keySet() for Android compatibility:
Iterator<String> iterator = o.keys();
while (iterator.hasNext()) {
String key = iterator.next();
Object value = o.get(key); Object value = o.get(key);
value = convertIfNecessary(value); value = convertIfNecessary(value);
map.put(key, value); map.put(key, value);
@ -67,8 +71,11 @@ public class OrgJsonDeserializer implements Deserializer<Object> {
} }
private List<Object> toList(JSONArray a) { private List<Object> toList(JSONArray a) {
List<Object> list = new ArrayList<>(a.length()); int length = a.length();
for (Object value : a.toList()) { List<Object> list = new ArrayList<>(length);
// https://github.com/jwtk/jjwt/issues/380: use a.get(i) and *not* a.toList() for Android compatibility:
for( int i = 0; i < length; i++) {
Object value = a.get(i);
value = convertIfNecessary(value); value = convertIfNecessary(value);
list.add(value); list.add(value);
} }

View File

@ -118,7 +118,22 @@ public class OrgJsonSerializer<T> implements Serializer<T> {
@SuppressWarnings("WeakerAccess") //for testing @SuppressWarnings("WeakerAccess") //for testing
protected byte[] toBytes(Object o) { protected byte[] toBytes(Object o) {
String s = JSONWriter.valueToString(o); String s;
// https://github.com/jwtk/jjwt/issues/380 for Android compatibility (Android doesn't have org.json.JSONWriter):
// This instanceof check is a sneaky (hacky?) heuristic: A JwtBuilder only ever provides Map<String,Object>
// instances to its serializer instances, so by the time this method is invoked, 'o' will always be a
// JSONObject.
//
// This is sufficient for all JJWT-supported scenarios on Android since Android users shouldn't ever use
// JJWT's internal Serializer implementation for general JSON serialization. That is, its intended use
// is within the context of JwtBuilder execution and not for application use outside of that.
if (o instanceof JSONObject) {
s = o.toString();
} else {
// we still call JSONWriter for all other values 'just in case', and this works for all valid JSON values
// This would fail on Android unless they include the newer org.json dependency and ignore Android's.
s = JSONWriter.valueToString(o);
}
return s.getBytes(Strings.UTF_8); return s.getBytes(Strings.UTF_8);
} }
} }

View File

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId> <artifactId>jjwt-root</artifactId>
<version>0.10.1</version> <version>0.10.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId> <artifactId>jjwt-root</artifactId>
<version>0.10.1</version> <version>0.10.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -25,7 +25,7 @@
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId> <artifactId>jjwt-root</artifactId>
<version>0.10.1</version> <version>0.10.2-SNAPSHOT</version>
<name>JJWT</name> <name>JJWT</name>
<description>JSON Web Token support for the JVM and Android</description> <description>JSON Web Token support for the JVM and Android</description>
<packaging>pom</packaging> <packaging>pom</packaging>
@ -43,7 +43,7 @@
<connection>scm:git:https://github.com/jwtk/jjwt.git</connection> <connection>scm:git:https://github.com/jwtk/jjwt.git</connection>
<developerConnection>scm:git:git@github.com:jwtk/jjwt.git</developerConnection> <developerConnection>scm:git:git@github.com:jwtk/jjwt.git</developerConnection>
<url>git@github.com:jwtk/jjwt.git</url> <url>git@github.com:jwtk/jjwt.git</url>
<tag>0.10.1</tag> <tag>0.10.2-SNAPSHOT</tag>
</scm> </scm>
<issueManagement> <issueManagement>
<system>GitHub Issues</system> <system>GitHub Issues</system>