15
15
16
16
import com .google .gson .Gson ;
17
17
import com .google .gson .GsonBuilder ;
18
+ import com .google .gson .JsonElement ;
18
19
import com .google .gson .JsonParseException ;
19
20
import com .google .gson .TypeAdapter ;
20
- import com .google .gson .internal .bind .util .ISO8601Utils ;
21
21
import com .google .gson .stream .JsonReader ;
22
22
import com .google .gson .stream .JsonWriter ;
23
- import com .google .gson .JsonElement ;
24
23
import io .gsonfire .GsonFireBuilder ;
25
- import io .gsonfire .TypeSelector ;
26
-
27
- import io .kubernetes .client .openapi .models .*;
28
- import okio .ByteString ;
29
-
24
+ import io .kubernetes .client .gson .V1StatusPreProcessor ;
25
+ import io .kubernetes .client .openapi .models .V1Status ;
30
26
import java .io .IOException ;
31
27
import java .io .StringReader ;
32
28
import java .lang .reflect .Type ;
33
29
import java .text .DateFormat ;
34
30
import java .text .ParseException ;
35
- import java .text . ParsePosition ;
31
+ import java .time . Instant ;
36
32
import java .time .LocalDate ;
37
33
import java .time .OffsetDateTime ;
38
34
import java .time .format .DateTimeFormatter ;
35
+ import java .time .format .DateTimeFormatterBuilder ;
36
+ import java .time .format .DateTimeParseException ;
37
+ import java .time .temporal .ChronoField ;
39
38
import java .util .Date ;
40
- import java .util .Locale ;
41
39
import java .util .Map ;
42
- import java . util . HashMap ;
40
+ import okio . ByteString ;
43
41
44
42
public class JSON {
43
+
45
44
private Gson gson ;
45
+
46
46
private boolean isLenientOnJson = false ;
47
+
48
+ private static final DateTimeFormatter RFC3339MICRO_FORMATTER =
49
+ new DateTimeFormatterBuilder ()
50
+ .parseDefaulting (ChronoField .OFFSET_SECONDS , 0 )
51
+ .append (DateTimeFormatter .ofPattern ("yyyy-MM-dd'T'HH:mm:ss" ))
52
+ .optionalStart ()
53
+ .appendFraction (ChronoField .NANO_OF_SECOND , 6 , 6 , true )
54
+ .optionalEnd ()
55
+ .appendOffsetId ()
56
+ .toFormatter ();
57
+
47
58
private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter ();
59
+
48
60
private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter ();
49
- private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter ();
61
+
62
+ private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter =
63
+ new OffsetDateTimeTypeAdapter (RFC3339MICRO_FORMATTER );
64
+
50
65
private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter ();
66
+
51
67
private ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter ();
52
68
53
69
public static GsonBuilder createGson () {
54
- GsonFireBuilder fireBuilder = new GsonFireBuilder ()
55
- ;
56
- GsonBuilder builder = fireBuilder .createGsonBuilder ();
70
+ GsonFireBuilder fireBuilder = new GsonFireBuilder ();
71
+ GsonBuilder builder =
72
+ fireBuilder
73
+ .registerPreProcessor (V1Status .class , new V1StatusPreProcessor ())
74
+ .createGsonBuilder ();
57
75
return builder ;
58
76
}
59
77
60
78
private static String getDiscriminatorValue (JsonElement readElement , String discriminatorField ) {
61
79
JsonElement element = readElement .getAsJsonObject ().get (discriminatorField );
62
80
if (null == element ) {
63
- throw new IllegalArgumentException ("missing discriminator field: <" + discriminatorField + ">" );
81
+ throw new IllegalArgumentException (
82
+ "missing discriminator field: <" + discriminatorField + ">" );
64
83
}
65
84
return element .getAsString ();
66
85
}
67
86
68
87
/**
69
- * Returns the Java class that implements the OpenAPI schema for the specified discriminator value.
88
+ * Returns the Java class that implements the OpenAPI schema for the specified discriminator
89
+ * value.
70
90
*
71
91
* @param classByDiscriminatorValue The map of discriminator values to Java classes.
72
92
* @param discriminatorValue The value of the OpenAPI discriminator in the input data.
73
93
* @return The Java class that implements the OpenAPI schema
74
94
*/
75
- private static Class getClassByDiscriminator (Map classByDiscriminatorValue , String discriminatorValue ) {
95
+ private static Class getClassByDiscriminator (
96
+ Map classByDiscriminatorValue , String discriminatorValue ) {
76
97
Class clazz = (Class ) classByDiscriminatorValue .get (discriminatorValue );
77
98
if (null == clazz ) {
78
- throw new IllegalArgumentException ("cannot determine model class of name: <" + discriminatorValue + ">" );
99
+ throw new IllegalArgumentException (
100
+ "cannot determine model class of name: <" + discriminatorValue + ">" );
79
101
}
80
102
return clazz ;
81
103
}
82
104
83
105
public JSON () {
84
- gson = createGson ()
85
- .registerTypeAdapter (Date .class , dateTypeAdapter )
86
- .registerTypeAdapter (java .sql .Date .class , sqlDateTypeAdapter )
87
- .registerTypeAdapter (OffsetDateTime .class , offsetDateTimeTypeAdapter )
88
- .registerTypeAdapter (LocalDate .class , localDateTypeAdapter )
89
- .registerTypeAdapter (byte [].class , byteArrayAdapter )
90
- .create ();
106
+ gson =
107
+ createGson ()
108
+ .registerTypeAdapter (Date .class , dateTypeAdapter )
109
+ .registerTypeAdapter (java .sql .Date .class , sqlDateTypeAdapter )
110
+ .registerTypeAdapter (OffsetDateTime .class , offsetDateTimeTypeAdapter )
111
+ .registerTypeAdapter (LocalDate .class , localDateTypeAdapter )
112
+ .registerTypeAdapter (byte [].class , byteArrayAdapter )
113
+ .create ();
91
114
}
92
115
93
116
/**
@@ -128,8 +151,8 @@ public String serialize(Object obj) {
128
151
/**
129
152
* Deserialize the given JSON string to Java object.
130
153
*
131
- * @param <T> Type
132
- * @param body The JSON string
154
+ * @param <T> Type
155
+ * @param body The JSON string
133
156
* @param returnType The type to deserialize into
134
157
* @return The deserialized Java object
135
158
*/
@@ -138,7 +161,8 @@ public <T> T deserialize(String body, Type returnType) {
138
161
try {
139
162
if (isLenientOnJson ) {
140
163
JsonReader jsonReader = new JsonReader (new StringReader (body ));
141
- // see https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean)
164
+ // see
165
+ // https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean)
142
166
jsonReader .setLenient (true );
143
167
return gson .fromJson (jsonReader , returnType );
144
168
} else {
@@ -155,18 +179,19 @@ public <T> T deserialize(String body, Type returnType) {
155
179
}
156
180
}
157
181
158
- /**
159
- * Gson TypeAdapter for Byte Array type
160
- */
182
+ /** Gson TypeAdapter for Byte Array type */
161
183
public class ByteArrayAdapter extends TypeAdapter <byte []> {
162
184
163
185
@ Override
164
186
public void write (JsonWriter out , byte [] value ) throws IOException {
187
+ boolean oldHtmlSafe = out .isHtmlSafe ();
188
+ out .setHtmlSafe (false );
165
189
if (value == null ) {
166
190
out .nullValue ();
167
191
} else {
168
192
out .value (ByteString .of (value ).base64 ());
169
193
}
194
+ out .setHtmlSafe (oldHtmlSafe );
170
195
}
171
196
172
197
@ Override
@@ -183,9 +208,7 @@ public byte[] read(JsonReader in) throws IOException {
183
208
}
184
209
}
185
210
186
- /**
187
- * Gson TypeAdapter for JSR310 OffsetDateTime type
188
- */
211
+ /** Gson TypeAdapter for JSR310 OffsetDateTime type */
189
212
public static class OffsetDateTimeTypeAdapter extends TypeAdapter <OffsetDateTime > {
190
213
191
214
private DateTimeFormatter formatter ;
@@ -220,16 +243,19 @@ public OffsetDateTime read(JsonReader in) throws IOException {
220
243
default :
221
244
String date = in .nextString ();
222
245
if (date .endsWith ("+0000" )) {
223
- date = date .substring (0 , date .length ()-5 ) + "Z" ;
246
+ date = date .substring (0 , date .length () - 5 ) + "Z" ;
247
+ }
248
+ try {
249
+ return OffsetDateTime .parse (date , formatter );
250
+ } catch (DateTimeParseException e ) {
251
+ // backward-compatibility for ISO8601 timestamp format
252
+ return OffsetDateTime .parse (date , DateTimeFormatter .ISO_OFFSET_DATE_TIME );
224
253
}
225
- return OffsetDateTime .parse (date , formatter );
226
254
}
227
255
}
228
256
}
229
257
230
- /**
231
- * Gson TypeAdapter for JSR310 LocalDate type
232
- */
258
+ /** Gson TypeAdapter for JSR310 LocalDate type */
233
259
public class LocalDateTypeAdapter extends TypeAdapter <LocalDate > {
234
260
235
261
private DateTimeFormatter formatter ;
@@ -279,9 +305,8 @@ public JSON setLocalDateFormat(DateTimeFormatter dateFormat) {
279
305
}
280
306
281
307
/**
282
- * Gson TypeAdapter for java.sql.Date type
283
- * If the dateFormat is null, a simple "yyyy-MM-dd" format will be used
284
- * (more efficient than SimpleDateFormat).
308
+ * Gson TypeAdapter for java.sql.Date type If the dateFormat is null, a simple "yyyy-MM-dd" format
309
+ * will be used (more efficient than SimpleDateFormat).
285
310
*/
286
311
public static class SqlDateTypeAdapter extends TypeAdapter <java .sql .Date > {
287
312
@@ -324,7 +349,8 @@ public java.sql.Date read(JsonReader in) throws IOException {
324
349
if (dateFormat != null ) {
325
350
return new java .sql .Date (dateFormat .parse (date ).getTime ());
326
351
}
327
- return new java .sql .Date (ISO8601Utils .parse (date , new ParsePosition (0 )).getTime ());
352
+ return new java .sql .Date (
353
+ Instant .from (DateTimeFormatter .ISO_INSTANT .parse (date )).toEpochMilli ());
328
354
} catch (ParseException e ) {
329
355
throw new JsonParseException (e );
330
356
}
@@ -333,8 +359,7 @@ public java.sql.Date read(JsonReader in) throws IOException {
333
359
}
334
360
335
361
/**
336
- * Gson TypeAdapter for java.util.Date type
337
- * If the dateFormat is null, ISO8601Utils will be used.
362
+ * Gson TypeAdapter for java.util.Date type If the dateFormat is null, ISO8601Utils will be used.
338
363
*/
339
364
public static class DateTypeAdapter extends TypeAdapter <Date > {
340
365
@@ -359,7 +384,7 @@ public void write(JsonWriter out, Date date) throws IOException {
359
384
if (dateFormat != null ) {
360
385
value = dateFormat .format (date );
361
386
} else {
362
- value = ISO8601Utils . format (date , true );
387
+ value = DateTimeFormatter . ISO_INSTANT . format (date . toInstant () );
363
388
}
364
389
out .value (value );
365
390
}
@@ -378,7 +403,7 @@ public Date read(JsonReader in) throws IOException {
378
403
if (dateFormat != null ) {
379
404
return dateFormat .parse (date );
380
405
}
381
- return ISO8601Utils . parse (date , new ParsePosition ( 0 ));
406
+ return Date . from ( Instant . from ( DateTimeFormatter . ISO_INSTANT . parse (date ) ));
382
407
} catch (ParseException e ) {
383
408
throw new JsonParseException (e );
384
409
}
@@ -398,5 +423,4 @@ public JSON setSqlDateFormat(DateFormat dateFormat) {
398
423
sqlDateTypeAdapter .setFormat (dateFormat );
399
424
return this ;
400
425
}
401
-
402
426
}
0 commit comments