Skip to content

Commit 0921e29

Browse files
author
Pieter Van Eeckhout
committed
jwtk#235 Update JWT for default Instant usage
The JWT handling has been updated to default to Java's Instant class. This change removed support for various date and time classes such as ZonedDateTime, OffsetDateTime, Date, and Calendar in favor of an Instant-based approach throughout the codebase. The appropriate tests and documentation were updated to reflect this change.
1 parent 9bdbb85 commit 0921e29

File tree

8 files changed

+23
-132
lines changed

8 files changed

+23
-132
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2992,7 +2992,7 @@ Jwts.parser()
29922992
<a name="json-jackson-custom-types"></a>
29932993
#### Parsing of Custom Claim Types
29942994

2995-
By default JJWT will only convert simple claim types: String, Date, Long, Integer, Short and Byte. If you need to
2995+
By default JJWT will only convert simple claim types: String, Instant, Long, Integer, Short and Byte. If you need to
29962996
deserialize other types you can configure the `JacksonDeserializer` by passing a `Map` of claim names to types in
29972997
through a constructor. For example:
29982998

api/src/main/java/io/jsonwebtoken/Claims.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public interface Claims extends Map<String, Object>, Identifiable {
147147
* Returns the JWTs claim ({@code claimName}) value as a {@code requiredType} instance, or {@code null} if not
148148
* present.
149149
*
150-
* <p>JJWT only converts simple String, Date, OffsetDateTime, ZonedDateTime, Long, Integer, Short and Byte types automatically. Anything more
150+
* <p>JJWT only converts simple String, Instant, Long, Integer, Short and Byte types automatically. Anything more
151151
* complex is expected to be already converted to your desired type by the JSON parser. You may specify a custom
152152
* JSON processor using the {@code JwtParserBuilder}'s
153153
* {@link JwtParserBuilder#json(io.jsonwebtoken.io.Deserializer) json(Deserializer)} method. See the JJWT

extensions/orgjson/src/main/java/io/jsonwebtoken/orgjson/io/OrgJsonSerializer.java

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@
3131
import java.math.BigDecimal;
3232
import java.math.BigInteger;
3333
import java.time.Instant;
34-
import java.time.OffsetDateTime;
35-
import java.time.ZonedDateTime;
36-
import java.util.Calendar;
3734
import java.util.Collection;
38-
import java.util.Date;
3935
import java.util.Map;
4036

4137
/**
@@ -96,26 +92,10 @@ private Object toJSONInstance(Object object) throws IOException {
9692
return object;
9793
}
9894

99-
if(object instanceof Instant) {
95+
if (object instanceof Instant) {
10096
return DateFormats.formatIso8601((Instant) object);
10197
}
10298

103-
if(object instanceof OffsetDateTime) {
104-
return DateFormats.formatIso8601(((OffsetDateTime) object).toInstant());
105-
}
106-
107-
if(object instanceof ZonedDateTime) {
108-
return DateFormats.formatIso8601(((ZonedDateTime) object).toInstant());
109-
}
110-
111-
if (object instanceof Calendar) {
112-
return DateFormats.formatIso8601(((Calendar) object).getTime().toInstant());
113-
}
114-
115-
if (object instanceof Date) {
116-
return DateFormats.formatIso8601(((Date) object).toInstant());
117-
}
118-
11999
if (object instanceof byte[]) {
120100
return Encoders.BASE64.encode((byte[]) object);
121101
}

extensions/orgjson/src/test/groovy/io/jsonwebtoken/orgjson/io/OrgJsonSerializerTest.groovy

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ import org.junit.Before
2828
import org.junit.Test
2929

3030
import java.time.Instant
31-
import java.time.OffsetDateTime
32-
import java.time.ZonedDateTime
3331

3432
import static org.junit.Assert.*
3533

@@ -201,22 +199,6 @@ class OrgJsonSerializerTest {
201199
assertEquals "\"$formatted\"" as String, ser(instant)
202200
}
203201

204-
@Test
205-
void testOffsetDateTime() {
206-
OffsetDateTime offsetDateTime = OffsetDateTime.now()
207-
def now = offsetDateTime.toInstant()
208-
String formatted = DateFormats.formatIso8601(now)
209-
assertEquals "\"$formatted\"" as String, ser(offsetDateTime)
210-
}
211-
212-
@Test
213-
void testZonedDateTime() {
214-
ZonedDateTime zonedDateTime = ZonedDateTime.now()
215-
def now = zonedDateTime.toInstant()
216-
String formatted = DateFormats.formatIso8601(now)
217-
assertEquals "\"$formatted\"" as String, ser(zonedDateTime)
218-
}
219-
220202
@Test
221203
void testDate() {
222204
Date date = new Date()
@@ -225,14 +207,6 @@ class OrgJsonSerializerTest {
225207
assertEquals "\"$formatted\"" as String, ser(date)
226208
}
227209

228-
@Test
229-
void testCalendar() {
230-
def cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
231-
def now = cal.toInstant()
232-
String formatted = DateFormats.formatIso8601(now)
233-
assertEquals "\"$formatted\"" as String, ser(cal)
234-
}
235-
236210
@Test
237211
void testSimpleIntArray() {
238212
assertEquals '[1,2]', ser([1, 2] as int[])

impl/src/main/java/io/jsonwebtoken/impl/DefaultClaims.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
public class DefaultClaims extends ParameterMap implements Claims {
3131

3232
private static final String CONVERSION_ERROR_MSG = "Cannot convert existing claim value of type '%s' to desired type " +
33-
"'%s'. JJWT only converts simple String, Date, Instant, OffsetDateTime, ZonedDateTime, Long, Integer, Short " +
33+
"'%s'. JJWT only converts simple String, Instant, Long, Integer, Short " +
3434
"and Byte types automatically. Anything more complex is expected to be already converted to your desired type " +
3535
"by the JSON Deserializer implementation. You may specify a custom Deserializer for a JwtParser with the " +
3636
"desired conversion configuration via the JwtParserBuilder.deserializer() method. " +

impl/src/main/java/io/jsonwebtoken/impl/lang/JwtDateConverter.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@
1818
import io.jsonwebtoken.lang.DateFormats;
1919

2020
import java.time.Instant;
21-
import java.time.ZonedDateTime;
22-
import java.time.OffsetDateTime;
2321
import java.time.format.DateTimeParseException;
24-
import java.util.Date;
25-
import java.util.Calendar;
2622

2723
public class JwtDateConverter implements Converter<Instant, Object> {
2824

@@ -51,7 +47,7 @@ public static Instant toSpecInstant(Object value) {
5147
long seconds = ((Number) value).longValue();
5248
value = Instant.ofEpochSecond(seconds);
5349
}
54-
// would have been normalized to Instant if it was a number value, so perform normal date conversion:
50+
// would have been normalized to Instant if it was a number value, so perform normal instant conversion:
5551
return toInstant(value);
5652
}
5753

@@ -66,20 +62,9 @@ public static Instant toInstant(Object v) {
6662
return null;
6763
} else if (v instanceof Instant) {
6864
return (Instant) v;
69-
} else if (v instanceof ZonedDateTime) {
70-
return ((ZonedDateTime) v).toInstant();
71-
}else if (v instanceof OffsetDateTime) {
72-
return ((OffsetDateTime) v).toInstant();
73-
} else if (v instanceof Date) {
74-
//assume UTC
75-
return ((Date) v).toInstant();
76-
} else if (v instanceof Calendar) { //since 0.10.0
77-
//assume UTC
78-
return ((Calendar) v).getTime().toInstant();
7965
} else if (v instanceof Number) {
8066
//assume millis:
8167
long millis = ((Number) v).longValue();
82-
//assume UTC
8368
return Instant.ofEpochMilli(millis);
8469
} else if (v instanceof String) {
8570
return parseIso8601Date((String) v); //ISO-8601 parsing since 0.10.0

impl/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,10 @@ class JwtsTest {
5353
return new Date(secondOnlyPrecisionMillis)
5454
}
5555

56-
private static Instant instantWithOnlySecondPrecision(long millis) {
57-
return instantWithOnlySecondPrecision(Instant.ofEpochMilli(millis))
58-
}
59-
6056
private static Instant instantWithOnlySecondPrecision(Instant instant) {
6157
return instant.truncatedTo(ChronoUnit.SECONDS)
6258
}
6359

64-
private static Date now() {
65-
Date date = dateWithOnlySecondPrecision(System.currentTimeMillis())
66-
return date
67-
}
68-
6960
private static int later() {
7061
def date = laterDate(10000)
7162
def seconds = date.getTime() / 1000

impl/src/test/groovy/io/jsonwebtoken/impl/DefaultClaimsTest.groovy

Lines changed: 18 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@ import org.junit.Before
2323
import org.junit.Test
2424

2525
import java.time.Instant
26-
import java.time.OffsetDateTime
27-
import java.time.ZonedDateTime
2826
import java.time.temporal.ChronoUnit
29-
import java.time.temporal.TemporalField
30-
import java.time.temporal.TemporalUnit
3127

3228
import static org.junit.Assert.*
3329

@@ -192,39 +188,6 @@ class DefaultClaimsTest {
192188
assertEquals expected, result
193189
}
194190

195-
@Test
196-
void testGetRequiredDateFromOffsetDateTime() {
197-
def expected = OffsetDateTime.now()
198-
claims.put("anOffsetDateTime", expected)
199-
OffsetDateTime result = claims.get("anOffsetDateTime", OffsetDateTime.class)
200-
assertEquals expected, result
201-
}
202-
203-
@Test
204-
void testGetRequiredDateFromZonedDateTime() {
205-
def expected = ZonedDateTime.now()
206-
claims.put("aZonedDateTime", expected)
207-
ZonedDateTime result = claims.get("aZonedDateTime", ZonedDateTime.class)
208-
assertEquals expected, result
209-
}
210-
211-
@Test
212-
void testGetRequiredDateFromDate() {
213-
def expected = new Date()
214-
claims.put("aDate", expected)
215-
Date result = claims.get("aDate", Date.class)
216-
assertEquals expected, result
217-
}
218-
219-
@Test
220-
void testGetRequiredDateFromCalendar() {
221-
def c = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
222-
def expected = c.toInstant()
223-
claims.put("aCalender", c)
224-
Instant result = claims.get('aCalender', Instant.class)
225-
assertEquals expected, result
226-
}
227-
228191
@Test
229192
void testGetRequiredDateFromLong() {
230193
def expected = Instant.now()
@@ -342,13 +305,12 @@ class DefaultClaimsTest {
342305
}
343306

344307
@Test
345-
void testGetSpecDateWithCalendar() {
346-
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
347-
Instant instant = cal.toInstant()
308+
void testGetSpecDateWithInstant() {
309+
Instant instant = Instant.now()
348310
long seconds = instant.getEpochSecond()
349-
claims.put(Claims.EXPIRATION, cal)
350-
claims.put(Claims.ISSUED_AT, cal)
351-
claims.put(Claims.NOT_BEFORE, cal)
311+
claims.put(Claims.EXPIRATION, instant)
312+
claims.put(Claims.ISSUED_AT, instant)
313+
claims.put(Claims.NOT_BEFORE, instant)
352314
assertEquals instant, claims.getExpiration()
353315
assertEquals instant, claims.getIssuedAt()
354316
assertEquals instant, claims.getNotBefore()
@@ -358,11 +320,10 @@ class DefaultClaimsTest {
358320
}
359321

360322
@Test
361-
void testToSpecDateWithDate() {
362-
long millis = System.currentTimeMillis()
363-
Date d = new Date(millis)
364-
claims.put('exp', d)
365-
assertEquals d.toInstant(), claims.getExpiration()
323+
void testToSpecDateWithInstant() {
324+
Instant i = Instant.now()
325+
claims.put('exp', i)
326+
assertEquals i, claims.getExpiration()
366327
}
367328

368329
void trySpecDateNonDate(Parameter<?> param) {
@@ -411,7 +372,7 @@ class DefaultClaimsTest {
411372
void testPutWithIat() {
412373
long millis = System.currentTimeMillis()
413374
long seconds = millis / 1000 as long
414-
Date now = new Date(millis)
375+
Instant now = Instant.ofEpochMilli(millis)
415376
claims.put('iat', now) //this should convert 'now' to seconds since epoch
416377
assertEquals seconds, claims.get('iat') //conversion should have happened
417378
}
@@ -420,7 +381,7 @@ class DefaultClaimsTest {
420381
void testPutAllWithIat() {
421382
long millis = System.currentTimeMillis()
422383
long seconds = millis / 1000 as long
423-
Date now = new Date(millis)
384+
Instant now = Instant.ofEpochMilli(millis)
424385
claims.putAll([iat: now]) //this should convert 'now' to seconds since epoch
425386
assertEquals seconds, claims.get('iat') //conversion should have happened
426387
}
@@ -429,7 +390,7 @@ class DefaultClaimsTest {
429390
void testConstructorWithIat() {
430391
long millis = System.currentTimeMillis()
431392
long seconds = millis / 1000 as long
432-
Date now = new Date(millis)
393+
Instant now = Instant.ofEpochMilli(millis)
433394
this.claims = new DefaultClaims([iat: now]) //this should convert 'now' to seconds since epoch
434395
assertEquals seconds, claims.get('iat') //conversion should have happened
435396
}
@@ -438,7 +399,7 @@ class DefaultClaimsTest {
438399
void testPutWithNbf() {
439400
long millis = System.currentTimeMillis()
440401
long seconds = millis / 1000 as long
441-
Date now = new Date(millis)
402+
Instant now = Instant.ofEpochMilli(millis)
442403
claims.put('nbf', now) //this should convert 'now' to seconds since epoch
443404
assertEquals seconds, claims.get('nbf') //conversion should have happened
444405
}
@@ -447,7 +408,7 @@ class DefaultClaimsTest {
447408
void testPutAllWithNbf() {
448409
long millis = System.currentTimeMillis()
449410
long seconds = millis / 1000 as long
450-
Date now = new Date(millis)
411+
Instant now = Instant.ofEpochMilli(millis)
451412
claims.putAll([nbf: now]) //this should convert 'now' to seconds since epoch
452413
assertEquals seconds, claims.get('nbf') //conversion should have happened
453414
}
@@ -456,7 +417,7 @@ class DefaultClaimsTest {
456417
void testConstructorWithNbf() {
457418
long millis = System.currentTimeMillis()
458419
long seconds = millis / 1000 as long
459-
Date now = new Date(millis)
420+
Instant now = Instant.ofEpochMilli(millis)
460421
this.claims = new DefaultClaims([nbf: now]) //this should convert 'now' to seconds since epoch
461422
assertEquals seconds, claims.get('nbf') //conversion should have happened
462423
}
@@ -465,7 +426,7 @@ class DefaultClaimsTest {
465426
void testPutWithExp() {
466427
long millis = System.currentTimeMillis()
467428
long seconds = millis / 1000 as long
468-
Date now = new Date(millis)
429+
Instant now = Instant.ofEpochMilli(millis)
469430
claims.put('exp', now) //this should convert 'now' to seconds since epoch
470431
assertEquals seconds, claims.get('exp') //conversion should have happened
471432
}
@@ -474,7 +435,7 @@ class DefaultClaimsTest {
474435
void testPutAllWithExp() {
475436
long millis = System.currentTimeMillis()
476437
long seconds = millis / 1000 as long
477-
Date now = new Date(millis)
438+
Instant now = Instant.ofEpochMilli(millis)
478439
claims.putAll([exp: now]) //this should convert 'now' to seconds since epoch
479440
assertEquals seconds, claims.get('exp') //conversion should have happened
480441
}
@@ -483,7 +444,7 @@ class DefaultClaimsTest {
483444
void testConstructorWithExp() {
484445
long millis = System.currentTimeMillis()
485446
long seconds = millis / 1000 as long
486-
Date now = new Date(millis)
447+
Instant now = Instant.ofEpochMilli(millis)
487448
this.claims = new DefaultClaims([exp: now]) //this should convert 'now' to seconds since epoch
488449
assertEquals seconds, claims.get('exp') //conversion should have happened
489450
}

0 commit comments

Comments
 (0)