Browse Source

Provide default values for Kotlinx Serialization JSON properties

Closes gh-48097
pull/48124/head
Andy Wilkinson 1 month ago
parent
commit
eb381d642a
  1. 25
      module/spring-boot-kotlinx-serialization-json/src/main/java/org/springframework/boot/kotlinx/serialization/json/autoconfigure/KotlinxSerializationJsonAutoConfiguration.java
  2. 109
      module/spring-boot-kotlinx-serialization-json/src/main/java/org/springframework/boot/kotlinx/serialization/json/autoconfigure/KotlinxSerializationJsonProperties.java
  3. 99
      module/spring-boot-kotlinx-serialization-json/src/test/java/org/springframework/boot/kotlinx/serialization/json/autoconfigure/KotlinxSerializationJsonPropertiesTests.java

25
module/spring-boot-kotlinx-serialization-json/src/main/java/org/springframework/boot/kotlinx/serialization/json/autoconfigure/KotlinxSerializationJsonAutoConfiguration.java

@ -81,21 +81,20 @@ public final class KotlinxSerializationJsonAutoConfiguration { @@ -81,21 +81,20 @@ public final class KotlinxSerializationJsonAutoConfiguration {
KotlinxSerializationJsonProperties properties = this.properties;
PropertyMapper map = PropertyMapper.get();
map.from(properties::getNamingStrategy).to(setNamingStrategy(jsonBuilder));
map.from(properties::getPrettyPrint).to(jsonBuilder::setPrettyPrint);
map.from(properties::getLenient).to(jsonBuilder::setLenient);
map.from(properties::getIgnoreUnknownKeys).to(jsonBuilder::setIgnoreUnknownKeys);
map.from(properties::getEncodeDefaults).to(jsonBuilder::setEncodeDefaults);
map.from(properties::getExplicitNulls).to(jsonBuilder::setExplicitNulls);
map.from(properties::getCoerceInputValues).to(jsonBuilder::setCoerceInputValues);
map.from(properties::getAllowStructuredMapKeys).to(jsonBuilder::setAllowStructuredMapKeys);
map.from(properties::getAllowSpecialFloatingPointValues)
.to(jsonBuilder::setAllowSpecialFloatingPointValues);
map.from(properties::isPrettyPrint).to(jsonBuilder::setPrettyPrint);
map.from(properties::isLenient).to(jsonBuilder::setLenient);
map.from(properties::isIgnoreUnknownKeys).to(jsonBuilder::setIgnoreUnknownKeys);
map.from(properties::isEncodeDefaults).to(jsonBuilder::setEncodeDefaults);
map.from(properties::isExplicitNulls).to(jsonBuilder::setExplicitNulls);
map.from(properties::isCoerceInputValues).to(jsonBuilder::setCoerceInputValues);
map.from(properties::isAllowStructuredMapKeys).to(jsonBuilder::setAllowStructuredMapKeys);
map.from(properties::isAllowSpecialFloatingPointValues).to(jsonBuilder::setAllowSpecialFloatingPointValues);
map.from(properties::getClassDiscriminator).to(jsonBuilder::setClassDiscriminator);
map.from(properties::getClassDiscriminatorMode).to(jsonBuilder::setClassDiscriminatorMode);
map.from(properties::getDecodeEnumsCaseInsensitive).to(jsonBuilder::setDecodeEnumsCaseInsensitive);
map.from(properties::getUseAlternativeNames).to(jsonBuilder::setUseAlternativeNames);
map.from(properties::getAllowTrailingComma).to(jsonBuilder::setAllowTrailingComma);
map.from(properties::getAllowComments).to(jsonBuilder::setAllowComments);
map.from(properties::isDecodeEnumsCaseInsensitive).to(jsonBuilder::setDecodeEnumsCaseInsensitive);
map.from(properties::isUseAlternativeNames).to(jsonBuilder::setUseAlternativeNames);
map.from(properties::isAllowTrailingComma).to(jsonBuilder::setAllowTrailingComma);
map.from(properties::isAllowComments).to(jsonBuilder::setAllowComments);
}
private Consumer<KotlinxSerializationJsonProperties.JsonNamingStrategy> setNamingStrategy(JsonBuilder builder) {

109
module/spring-boot-kotlinx-serialization-json/src/main/java/org/springframework/boot/kotlinx/serialization/json/autoconfigure/KotlinxSerializationJsonProperties.java

@ -38,83 +38,82 @@ public class KotlinxSerializationJsonProperties { @@ -38,83 +38,82 @@ public class KotlinxSerializationJsonProperties {
private @Nullable JsonNamingStrategy namingStrategy;
/**
* Whether resulting JSON should be pretty-printed: formatted and optimized for human
* readability.
* Whether resulting JSON should be pretty-printed.
*/
private @Nullable Boolean prettyPrint;
private boolean prettyPrint;
/**
* Enable lenient mode that removes JSON specification restriction (RFC-4627) and
* makes parser more liberal to the malformed input.
* Whether parser should operate in lenient mode, removing the JSON specification
* restriction (RFC-4627) and being more liberal to malformed input.
*/
private @Nullable Boolean lenient;
private boolean lenient;
/**
* Whether encounters of unknown properties in the input JSON should be ignored
* instead of throwing SerializationException.
*/
private @Nullable Boolean ignoreUnknownKeys;
private boolean ignoreUnknownKeys;
/**
* Whether default values of Kotlin properties should be encoded.
*/
private @Nullable Boolean encodeDefaults;
private boolean encodeDefaults;
/**
* Whether null values should be encoded for nullable properties and must be present
* in JSON object during decoding.
*/
private @Nullable Boolean explicitNulls;
private boolean explicitNulls = true;
/**
* Enable coercing incorrect JSON values.
* Whether to coerce incorrect JSON values.
*/
private @Nullable Boolean coerceInputValues;
private boolean coerceInputValues;
/**
* Enable structured objects to be serialized as map keys by changing serialized form
* of the map from JSON object (key-value pairs) to flat array like [k1, v1, k2, v2].
* Whether to allow structured objects to be serialized as map keys by changing the
* serialized form of the map from JSON object (key-value pairs) to flat array like
* [k1, v1, k2, v2].
*/
private @Nullable Boolean allowStructuredMapKeys;
private boolean allowStructuredMapKeys;
/**
* Whether to remove JSON specification restriction on special floating-point values
* such as 'NaN' and 'Infinity' and enable their serialization and deserialization as
* float literals without quotes.
* Whether to remove the JSON specification restriction on special floating-point
* values such as 'NaN' and 'Infinity' and allow their serialization and
* deserialization as float literals without quotes.
*/
private @Nullable Boolean allowSpecialFloatingPointValues;
private boolean allowSpecialFloatingPointValues;
/**
* Name of the class descriptor property for polymorphic serialization.
*/
private @Nullable String classDiscriminator;
private String classDiscriminator = "type";
/**
* Defines which classes and objects should have class discriminator added to the
* output.
*/
private @Nullable ClassDiscriminatorMode classDiscriminatorMode;
private ClassDiscriminatorMode classDiscriminatorMode = ClassDiscriminatorMode.POLYMORPHIC;
/**
* Enable decoding enum values in a case-insensitive manner.
* Whether enum values are decoded in a case-insensitive manner.
*/
private @Nullable Boolean decodeEnumsCaseInsensitive;
private boolean decodeEnumsCaseInsensitive;
/**
* Whether Json instance makes use of JsonNames annotation.
*/
private @Nullable Boolean useAlternativeNames;
private boolean useAlternativeNames = true;
/**
* Whether to allow parser to accept trailing (ending) commas in JSON objects and
* arrays.
* Whether to allow parser to accept trailing commas in JSON objects and arrays.
*/
private @Nullable Boolean allowTrailingComma;
private boolean allowTrailingComma;
/**
* Whether to allow parser to accept C/Java-style comments in JSON input.
*/
private @Nullable Boolean allowComments;
private boolean allowComments;
public @Nullable JsonNamingStrategy getNamingStrategy() {
return this.namingStrategy;
@ -124,115 +123,115 @@ public class KotlinxSerializationJsonProperties { @@ -124,115 +123,115 @@ public class KotlinxSerializationJsonProperties {
this.namingStrategy = namingStrategy;
}
public @Nullable Boolean getPrettyPrint() {
public boolean isPrettyPrint() {
return this.prettyPrint;
}
public void setPrettyPrint(@Nullable Boolean prettyPrint) {
public void setPrettyPrint(boolean prettyPrint) {
this.prettyPrint = prettyPrint;
}
public @Nullable Boolean getLenient() {
public boolean isLenient() {
return this.lenient;
}
public void setLenient(@Nullable Boolean lenient) {
public void setLenient(boolean lenient) {
this.lenient = lenient;
}
public @Nullable Boolean getIgnoreUnknownKeys() {
public boolean isIgnoreUnknownKeys() {
return this.ignoreUnknownKeys;
}
public void setIgnoreUnknownKeys(@Nullable Boolean ignoreUnknownKeys) {
public void setIgnoreUnknownKeys(boolean ignoreUnknownKeys) {
this.ignoreUnknownKeys = ignoreUnknownKeys;
}
public @Nullable Boolean getEncodeDefaults() {
public boolean isEncodeDefaults() {
return this.encodeDefaults;
}
public void setEncodeDefaults(@Nullable Boolean encodeDefaults) {
public void setEncodeDefaults(boolean encodeDefaults) {
this.encodeDefaults = encodeDefaults;
}
public @Nullable Boolean getExplicitNulls() {
public boolean isExplicitNulls() {
return this.explicitNulls;
}
public void setExplicitNulls(@Nullable Boolean explicitNulls) {
public void setExplicitNulls(boolean explicitNulls) {
this.explicitNulls = explicitNulls;
}
public @Nullable Boolean getCoerceInputValues() {
public boolean isCoerceInputValues() {
return this.coerceInputValues;
}
public void setCoerceInputValues(@Nullable Boolean coerceInputValues) {
public void setCoerceInputValues(boolean coerceInputValues) {
this.coerceInputValues = coerceInputValues;
}
public @Nullable Boolean getAllowStructuredMapKeys() {
public boolean isAllowStructuredMapKeys() {
return this.allowStructuredMapKeys;
}
public void setAllowStructuredMapKeys(@Nullable Boolean allowStructuredMapKeys) {
public void setAllowStructuredMapKeys(boolean allowStructuredMapKeys) {
this.allowStructuredMapKeys = allowStructuredMapKeys;
}
public @Nullable Boolean getAllowSpecialFloatingPointValues() {
public boolean isAllowSpecialFloatingPointValues() {
return this.allowSpecialFloatingPointValues;
}
public void setAllowSpecialFloatingPointValues(@Nullable Boolean allowSpecialFloatingPointValues) {
public void setAllowSpecialFloatingPointValues(boolean allowSpecialFloatingPointValues) {
this.allowSpecialFloatingPointValues = allowSpecialFloatingPointValues;
}
public @Nullable String getClassDiscriminator() {
public String getClassDiscriminator() {
return this.classDiscriminator;
}
public void setClassDiscriminator(@Nullable String classDiscriminator) {
public void setClassDiscriminator(String classDiscriminator) {
this.classDiscriminator = classDiscriminator;
}
public @Nullable ClassDiscriminatorMode getClassDiscriminatorMode() {
public ClassDiscriminatorMode getClassDiscriminatorMode() {
return this.classDiscriminatorMode;
}
public void setClassDiscriminatorMode(@Nullable ClassDiscriminatorMode classDiscriminatorMode) {
public void setClassDiscriminatorMode(ClassDiscriminatorMode classDiscriminatorMode) {
this.classDiscriminatorMode = classDiscriminatorMode;
}
public @Nullable Boolean getDecodeEnumsCaseInsensitive() {
public boolean isDecodeEnumsCaseInsensitive() {
return this.decodeEnumsCaseInsensitive;
}
public void setDecodeEnumsCaseInsensitive(@Nullable Boolean decodeEnumsCaseInsensitive) {
public void setDecodeEnumsCaseInsensitive(boolean decodeEnumsCaseInsensitive) {
this.decodeEnumsCaseInsensitive = decodeEnumsCaseInsensitive;
}
public @Nullable Boolean getUseAlternativeNames() {
public boolean isUseAlternativeNames() {
return this.useAlternativeNames;
}
public void setUseAlternativeNames(@Nullable Boolean useAlternativeNames) {
public void setUseAlternativeNames(boolean useAlternativeNames) {
this.useAlternativeNames = useAlternativeNames;
}
public @Nullable Boolean getAllowTrailingComma() {
public boolean isAllowTrailingComma() {
return this.allowTrailingComma;
}
public void setAllowTrailingComma(@Nullable Boolean allowTrailingComma) {
public void setAllowTrailingComma(boolean allowTrailingComma) {
this.allowTrailingComma = allowTrailingComma;
}
public @Nullable Boolean getAllowComments() {
public boolean isAllowComments() {
return this.allowComments;
}
public void setAllowComments(@Nullable Boolean allowComments) {
public void setAllowComments(boolean allowComments) {
this.allowComments = allowComments;
}

99
module/spring-boot-kotlinx-serialization-json/src/test/java/org/springframework/boot/kotlinx/serialization/json/autoconfigure/KotlinxSerializationJsonPropertiesTests.java

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.kotlinx.serialization.json.autoconfigure;
import kotlinx.serialization.json.Json;
import kotlinx.serialization.json.JsonBuilder;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link KotlinxSerializationJsonProperties}.
*
* @author Andy Wilkinson
*/
class KotlinxSerializationJsonPropertiesTests {
@ParameterizedTest
@EnumSource
void defaultsAreAligned(JsonBuilderSettings settings) {
JsonBuilder jsonBuilder = new JsonBuilder(Json.Default);
KotlinxSerializationJsonProperties properties = new KotlinxSerializationJsonProperties();
assertThat(settings.propertyGetter.get(properties)).isEqualTo(settings.jsonBuilderGetter.get(jsonBuilder));
}
private enum JsonBuilderSettings {
ALLOW_COMMENTS(KotlinxSerializationJsonProperties::isAllowComments, JsonBuilder::getAllowComments),
ALLOW_SPECIAL_FLOATING_POINT_VALUES(KotlinxSerializationJsonProperties::isAllowSpecialFloatingPointValues,
JsonBuilder::getAllowSpecialFloatingPointValues),
ALLOW_STRUCTURED_MAP_KEYS(KotlinxSerializationJsonProperties::isAllowStructuredMapKeys,
JsonBuilder::getAllowStructuredMapKeys),
ALLOW_TRAILING_COMMA(KotlinxSerializationJsonProperties::isAllowTrailingComma,
JsonBuilder::getAllowTrailingComma),
CLASS_DISCRIMINATOR(KotlinxSerializationJsonProperties::getClassDiscriminator,
JsonBuilder::getClassDiscriminator),
CLASS_DISCRIMINATOR_MODE(KotlinxSerializationJsonProperties::getClassDiscriminatorMode,
JsonBuilder::getClassDiscriminatorMode),
COERCE_INPUT_VALUES(KotlinxSerializationJsonProperties::isCoerceInputValues, JsonBuilder::getCoerceInputValues),
DECODE_ENUMS_CASE_INSENSITIVE(KotlinxSerializationJsonProperties::isDecodeEnumsCaseInsensitive,
JsonBuilder::getDecodeEnumsCaseInsensitive),
ENCODE_DEFAULTS(KotlinxSerializationJsonProperties::isEncodeDefaults, JsonBuilder::getEncodeDefaults),
EXPLICIT_NULLS(KotlinxSerializationJsonProperties::isExplicitNulls, JsonBuilder::getExplicitNulls),
IGNORE_UNKNOWN_KEYS(KotlinxSerializationJsonProperties::isIgnoreUnknownKeys, JsonBuilder::getIgnoreUnknownKeys),
LENIENT(KotlinxSerializationJsonProperties::isLenient, JsonBuilder::isLenient),
NAMING_STRATEGY(KotlinxSerializationJsonProperties::getNamingStrategy, JsonBuilder::getNamingStrategy),
PRETTY_PRINT(KotlinxSerializationJsonProperties::isPrettyPrint, JsonBuilder::getPrettyPrint),
USE_ALTERNATIVE_NAMES(KotlinxSerializationJsonProperties::isUseAlternativeNames,
JsonBuilder::getUseAlternativeNames);
private final Accessor<KotlinxSerializationJsonProperties, ?> propertyGetter;
private final Accessor<JsonBuilder, ?> jsonBuilderGetter;
JsonBuilderSettings(Accessor<KotlinxSerializationJsonProperties, @Nullable Object> propertyGetter,
Accessor<JsonBuilder, @Nullable Object> jsonBuilderGetter) {
this.propertyGetter = propertyGetter;
this.jsonBuilderGetter = jsonBuilderGetter;
}
private interface Accessor<S, @Nullable P extends @Nullable Object> {
@Nullable P get(S source);
}
}
}
Loading…
Cancel
Save