diff --git a/CHANGELOG.md b/CHANGELOG.md index e788acd514..c56abe8fa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### 6.13-SNAPSHOT #### Bugs +* Fix #5960: The serialization of time related types should be string * Fix #5866: Addressed cycle in crd generation with Java 19+ and ZonedDateTime #### Improvements @@ -17,6 +18,7 @@ #### New Features #### _**Note**_: Breaking changes +* Fix #5960: The KubernetesSerializer will now by default serialize time related types to strings - rather than object, integer, number, or arrays of integer / number. If you are using these types in a custom object and were not including JsonFormat annotations to adjust the serialization they were likely being serialized in a non-standard way that would not be usable other Kubernetes clients, nor match the generated custom resource definition if one was being produced. Please open an issue if you need the previous behavior for whatever reason - there is a workaround by creating a customized KubernetesSerializer. ### 6.12.1 (2024-04-18) diff --git a/crd-generator/test/src/test/java/io/fabric8/crd/generator/types/TypeMappingsTest.java b/crd-generator/test/src/test/java/io/fabric8/crd/generator/types/TypeMappingsTest.java index 5eda53475f..c8ba310005 100644 --- a/crd-generator/test/src/test/java/io/fabric8/crd/generator/types/TypeMappingsTest.java +++ b/crd-generator/test/src/test/java/io/fabric8/crd/generator/types/TypeMappingsTest.java @@ -52,17 +52,17 @@ void targetType(String propertyName, String expectedType) { private static Stream targetTypeCases() { return Stream.of( Arguments.of("date", "string"), - Arguments.of("localDate", "array"), // to review - Arguments.of("localDateTime", "array"), // to review - Arguments.of("zonedDateTime", "number"), // to review - Arguments.of("offsetDateTime", "number"), // to review - Arguments.of("offsetTime", "array"), // to review - Arguments.of("yearMonth", "array"), // to review - Arguments.of("monthDay", "array"), // to review - Arguments.of("instant", "number"), // to review - Arguments.of("duration", "integer"), // to review + Arguments.of("localDate", "string"), + Arguments.of("localDateTime", "string"), + Arguments.of("zonedDateTime", "string"), + Arguments.of("offsetDateTime", "string"), + Arguments.of("offsetTime", "string"), + Arguments.of("yearMonth", "string"), + Arguments.of("monthDay", "string"), + Arguments.of("instant", "string"), + Arguments.of("duration", "string"), Arguments.of("period", "string"), - Arguments.of("timestamp", "integer"), // to review + Arguments.of("timestamp", "string"), // to review // Arguments.of("aShort", "integer"), // TODO: Not even present in the CRD Arguments.of("aShortObj", "integer"), Arguments.of("aInt", "integer"), diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesSerialization.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesSerialization.java index 609bf20a0e..db04df0247 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesSerialization.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesSerialization.java @@ -27,6 +27,7 @@ import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationConfig; +import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.Annotated; @@ -90,6 +91,8 @@ public KubernetesSerialization(ObjectMapper mapper, boolean searchClassloaders) protected void configureMapper(ObjectMapper mapper) { mapper.registerModules(new JavaTimeModule(), unmatchedFieldTypeModule); mapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.disable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS); // omit null fields, but keep null map values mapper.setDefaultPropertyInclusion(JsonInclude.Value.construct(Include.NON_NULL, Include.ALWAYS)); HandlerInstantiator instanciator = mapper.getDeserializationConfig().getHandlerInstantiator();