Addressed issue where org.json.JSONString and org.json.JSONWriter are not available on Android. Resolves #388.

This commit is contained in:
Les Hazlewood 2018-08-15 10:28:28 -04:00
parent 33a3107213
commit 77f1a69c72
4 changed files with 76 additions and 17 deletions

View File

@ -1,5 +1,9 @@
## Release Notes
### 0.10.5
This patch release fixed an Android `org.json` library compatibility [issue](https://github.com/jwtk/jjwt/issues/388).
### 0.10.4
This patch release fixed an [outstanding issue](https://github.com/jwtk/jjwt/issues/381) with JCA name

View File

@ -179,18 +179,18 @@ If you're building a (non-Android) JDK project, you will want to define the foll
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.4</version>
<version>0.10.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.4</version>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.4</version>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
<!-- 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
dependencies {
compile 'io.jsonwebtoken:jjwt-api:0.10.4'
runtime 'io.jsonwebtoken:jjwt-impl:0.10.4',
compile 'io.jsonwebtoken:jjwt-api:0.10.5'
runtime 'io.jsonwebtoken:jjwt-impl:0.10.5',
// Uncomment the next line if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms:
//'org.bouncycastle:bcprov-jdk15on:1.60',
'io.jsonwebtoken:jjwt-jackson:0.10.4'
'io.jsonwebtoken:jjwt-jackson:0.10.5'
}
```
@ -229,9 +229,9 @@ Add the dependencies to your project:
```groovy
dependencies {
api 'io.jsonwebtoken:jjwt-api:0.10.4'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.10.4'
runtimeOnly('io.jsonwebtoken:jjwt-orgjson:0.10.4') {
api 'io.jsonwebtoken:jjwt-api:0.10.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.10.5'
runtimeOnly('io.jsonwebtoken:jjwt-orgjson:0.10.5') {
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:
@ -250,8 +250,6 @@ You can use the following [Android Proguard](https://developer.android.com/studi
-keep class io.jsonwebtoken.** { *; }
-keepnames class io.jsonwebtoken.* { *; }
-keepnames interface io.jsonwebtoken.* { *; }
-dontwarn org.json.JSONString
-dontwarn org.json.JSONWriter
-keep class org.bouncycastle.** { *; }
-keepnames class org.bouncycastle.** { *; }
@ -1194,7 +1192,7 @@ scope which is the typical JJWT default). That is:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.4</version>
<version>0.10.5</version>
<scope>compile</scope> <!-- Not runtime -->
</dependency>
```
@ -1203,7 +1201,7 @@ scope which is the typical JJWT default). That is:
```groovy
dependencies {
compile 'io.jsonwebtoken:jjwt-jackson:0.10.4'
compile 'io.jsonwebtoken:jjwt-jackson:0.10.5'
}
```

View File

@ -1,13 +1,12 @@
package io.jsonwebtoken.io;
import io.jsonwebtoken.lang.Classes;
import io.jsonwebtoken.lang.Collections;
import io.jsonwebtoken.lang.DateFormats;
import io.jsonwebtoken.lang.Objects;
import io.jsonwebtoken.lang.Strings;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONString;
import org.json.JSONWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -21,6 +20,20 @@ import java.util.Map;
*/
public class OrgJsonSerializer<T> implements Serializer<T> {
// we need reflection for these because of Android - see https://github.com/jwtk/jjwt/issues/388
private static final String JSON_WRITER_CLASS_NAME = "org.json.JSONWriter";
private static final Class[] VALUE_TO_STRING_ARG_TYPES = new Class[]{Object.class};
private static final String JSON_STRING_CLASS_NAME = "org.json.JSONString";
private static final Class JSON_STRING_CLASS;
static { // see see https://github.com/jwtk/jjwt/issues/388
if (Classes.isAvailable(JSON_STRING_CLASS_NAME)) {
JSON_STRING_CLASS = Classes.forName(JSON_STRING_CLASS_NAME);
} else {
JSON_STRING_CLASS = null;
}
}
@Override
public byte[] serialize(T t) throws SerializationException {
try {
@ -35,6 +48,16 @@ public class OrgJsonSerializer<T> implements Serializer<T> {
}
}
/**
* @since 0.10.5 see https://github.com/jwtk/jjwt/issues/388
*/
private static boolean isJSONString(Object o) {
if (JSON_STRING_CLASS != null) {
return JSON_STRING_CLASS.isInstance(o);
}
return false;
}
private Object toJSONInstance(Object object) {
if (object == null) {
@ -42,7 +65,7 @@ public class OrgJsonSerializer<T> implements Serializer<T> {
}
if (object instanceof JSONObject || object instanceof JSONArray
|| JSONObject.NULL.equals(object) || object instanceof JSONString
|| JSONObject.NULL.equals(object) || isJSONString(object)
|| object instanceof Byte || object instanceof Character
|| object instanceof Short || object instanceof Integer
|| object instanceof Long || object instanceof Boolean
@ -132,7 +155,7 @@ public class OrgJsonSerializer<T> implements Serializer<T> {
} 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);
s = Classes.invokeStatic(JSON_WRITER_CLASS_NAME, "valueToString", VALUE_TO_STRING_ARG_TYPES, o);
}
return s.getBytes(Strings.UTF_8);
}

View File

@ -0,0 +1,34 @@
package io.jsonwebtoken.io
import io.jsonwebtoken.lang.Classes
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import static org.easymock.EasyMock.eq
import static org.easymock.EasyMock.expect
import static org.junit.Assert.*
import static org.powermock.api.easymock.PowerMock.mockStatic
import static org.powermock.api.easymock.PowerMock.replay
import static org.powermock.api.easymock.PowerMock.verify
@RunWith(PowerMockRunner.class)
@PrepareForTest([Classes])
class AndroidOrgJsonSerializerTest {
@Test
void testJSONStringNotAvailable() {
mockStatic(Classes)
expect(Classes.isAvailable(eq('org.json.JSONString'))).andReturn(false)
replay Classes
assertFalse OrgJsonSerializer.isJSONString('foo')
verify Classes
}
}