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