|
24 | 24 | import io.gsonfire.GsonFireBuilder; |
25 | 25 | import io.gsonfire.TypeSelector; |
26 | 26 |
|
| 27 | +import io.kubernetes.client.gson.V1MetadataExclusionStrategy; |
| 28 | +import io.kubernetes.client.gson.V1StatusPreProcessor; |
| 29 | +import io.kubernetes.client.openapi.models.V1Status; |
27 | 30 | import okio.ByteString; |
28 | 31 |
|
29 | 32 | import java.io.IOException; |
|
38 | 41 | import java.time.LocalDate; |
39 | 42 | import java.time.OffsetDateTime; |
40 | 43 | import java.time.format.DateTimeFormatter; |
| 44 | +import java.time.format.DateTimeFormatterBuilder; |
| 45 | +import java.time.format.DateTimeParseException; |
| 46 | +import java.time.temporal.ChronoField; |
41 | 47 | import java.util.Date; |
42 | 48 | import java.util.Locale; |
43 | 49 | import java.util.Map; |
|
52 | 58 | public class JSON { |
53 | 59 | private static Gson gson; |
54 | 60 | private static boolean isLenientOnJson = false; |
| 61 | + |
| 62 | + private static final DateTimeFormatter RFC3339MICRO_FORMATTER = |
| 63 | + new DateTimeFormatterBuilder() |
| 64 | + .parseDefaulting(ChronoField.OFFSET_SECONDS, 0) |
| 65 | + .append(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")) |
| 66 | + .optionalStart() |
| 67 | + .appendFraction(ChronoField.NANO_OF_SECOND, 6, 6, true) |
| 68 | + .optionalEnd() |
| 69 | + .appendLiteral("Z") |
| 70 | + .toFormatter(); |
| 71 | + |
55 | 72 | private static DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); |
56 | 73 | private static SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); |
57 | | - private static OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(); |
| 74 | + private static OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(RFC3339MICRO_FORMATTER); |
58 | 75 | private static LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); |
59 | 76 | private static ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter(); |
60 | 77 |
|
61 | 78 | @SuppressWarnings("unchecked") |
62 | 79 | public static GsonBuilder createGson() { |
63 | 80 | GsonFireBuilder fireBuilder = new GsonFireBuilder() |
64 | 81 | ; |
65 | | - GsonBuilder builder = fireBuilder.createGsonBuilder(); |
66 | | - return builder; |
| 82 | + GsonBuilder builder = |
| 83 | + fireBuilder |
| 84 | + .registerPreProcessor(V1Status.class, new V1StatusPreProcessor()) |
| 85 | + .createGsonBuilder(); |
| 86 | + return builder.setExclusionStrategies(new V1MetadataExclusionStrategy()); |
67 | 87 | } |
68 | 88 |
|
69 | 89 | private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) { |
@@ -907,11 +927,14 @@ public static class ByteArrayAdapter extends TypeAdapter<byte[]> { |
907 | 927 |
|
908 | 928 | @Override |
909 | 929 | public void write(JsonWriter out, byte[] value) throws IOException { |
| 930 | + boolean oldHtmlSafe = out.isHtmlSafe(); |
| 931 | + out.setHtmlSafe(false); |
910 | 932 | if (value == null) { |
911 | 933 | out.nullValue(); |
912 | 934 | } else { |
913 | 935 | out.value(ByteString.of(value).base64()); |
914 | 936 | } |
| 937 | + out.setHtmlSafe(oldHtmlSafe); |
915 | 938 | } |
916 | 939 |
|
917 | 940 | @Override |
@@ -967,7 +990,12 @@ public OffsetDateTime read(JsonReader in) throws IOException { |
967 | 990 | if (date.endsWith("+0000")) { |
968 | 991 | date = date.substring(0, date.length()-5) + "Z"; |
969 | 992 | } |
970 | | - return OffsetDateTime.parse(date, formatter); |
| 993 | + try { |
| 994 | + return OffsetDateTime.parse(date, formatter); |
| 995 | + } catch (DateTimeParseException e) { |
| 996 | + // backward-compatibility for ISO8601 timestamp format |
| 997 | + return OffsetDateTime.parse(date, DateTimeFormatter.ISO_OFFSET_DATE_TIME); |
| 998 | + } |
971 | 999 | } |
972 | 1000 | } |
973 | 1001 | } |
|
0 commit comments