Skip to content

Commit

Permalink
Tolerate Gson 2.10 and earlier
Browse files Browse the repository at this point in the history
Closes gh-43442
  • Loading branch information
wilkinsona committed Jan 14, 2025
1 parent c66514c commit d4c7013
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
Expand All @@ -17,9 +17,11 @@
package org.springframework.boot.autoconfigure.gson;

import java.util.List;
import java.util.function.Consumer;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.Strictness;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
Expand All @@ -29,6 +31,7 @@
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.util.ClassUtils;

/**
* {@link EnableAutoConfiguration Auto-configuration} for Gson.
Expand Down Expand Up @@ -92,11 +95,23 @@ public void customize(GsonBuilder builder) {
map.from(properties::getLongSerializationPolicy).to(builder::setLongSerializationPolicy);
map.from(properties::getFieldNamingPolicy).to(builder::setFieldNamingPolicy);
map.from(properties::getPrettyPrinting).whenTrue().toCall(builder::setPrettyPrinting);
map.from(properties::getStrictness).to(builder::setStrictness);
map.from(properties::getStrictness).to(strictnessOrLeniency(builder));
map.from(properties::getDisableHtmlEscaping).whenTrue().toCall(builder::disableHtmlEscaping);
map.from(properties::getDateFormat).to(builder::setDateFormat);
}

@SuppressWarnings("deprecation")
private Consumer<GsonProperties.Strictness> strictnessOrLeniency(GsonBuilder builder) {
if (ClassUtils.isPresent("com.google.gson.Strictness", getClass().getClassLoader())) {
return (strictness) -> builder.setStrictness(Strictness.valueOf(strictness.name()));
}
return (strictness) -> {
if (strictness == GsonProperties.Strictness.LENIENT) {
builder.setLenient();
}
};
}

}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
Expand All @@ -19,7 +19,6 @@
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.LongSerializationPolicy;
import com.google.gson.Strictness;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
Expand Down Expand Up @@ -190,4 +189,30 @@ public void setDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}

/**
* Enumeration of levels of strictness. Values are the same as those on
* {@link com.google.gson.Strictness} that was introduced in Gson 2.11. To maximize
* backwards compatibility, the Gson enum is not used directly.
*
* @since 3.4.1
*/
public enum Strictness {

/**
* Lenient compliance.
*/
LENIENT,

/**
* Strict compliance with some small deviations for legacy reasons.
*/
LEGACY_STRICT,

/**
* Strict compliance.
*/
STRICT

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright 2012-2025 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.autoconfigure.gson;

import com.google.gson.Gson;
import org.junit.jupiter.api.Test;

import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link GsonAutoConfiguration} with Gson 2.10.
*
* @author Andy Wilkinson
*/
@ClassPathExclusions("gson-*.jar")
@ClassPathOverrides("com.google.code.gson:gson:2.10")
class Gson210AutoConfigurationTests {

private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(GsonAutoConfiguration.class));

@Test
void gsonRegistration() {
this.contextRunner.run((context) -> {
Gson gson = context.getBean(Gson.class);
assertThat(gson.toJson(new DataObject())).isEqualTo("{\"data\":1}");
});
}

@Test
@Deprecated(since = "3.4.0", forRemoval = true)
void withoutLenient() {
this.contextRunner.run((context) -> {
Gson gson = context.getBean(Gson.class);
assertThat(gson).hasFieldOrPropertyWithValue("lenient", false);
});
}

@Test
@Deprecated(since = "3.4.0", forRemoval = true)
void withLenientTrue() {
this.contextRunner.withPropertyValues("spring.gson.lenient:true").run((context) -> {
Gson gson = context.getBean(Gson.class);
assertThat(gson).hasFieldOrPropertyWithValue("lenient", true);
});
}

@Test
@Deprecated(since = "3.4.0", forRemoval = true)
void withLenientFalse() {
this.contextRunner.withPropertyValues("spring.gson.lenient:false").run((context) -> {
Gson gson = context.getBean(Gson.class);
assertThat(gson).hasFieldOrPropertyWithValue("lenient", false);
});
}

public class DataObject {

@SuppressWarnings("unused")
private Long data = 1L;

@SuppressWarnings("unused")
private final String owner = null;

public void setData(Long data) {
this.data = data;
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2012-2025 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.autoconfigure.gson;

import java.util.List;
import java.util.stream.Stream;

import com.google.gson.Strictness;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link GsonProperties}.
*
* @author Andy Wilkinson
*/
class GsonPropertiesTests {

@Test
void valuesOfOurStrictnessMatchValuesOfGsonsStrictness() {
assertThat(namesOf(GsonProperties.Strictness.values())).isEqualTo(namesOf(Strictness.values()));
}

private List<String> namesOf(Enum<?>[] input) {
return Stream.of(input).map(Enum::name).toList();
}

}

0 comments on commit d4c7013

Please sign in to comment.