Do not ignore null/empty values from SPRING_APPLICATION_JSON

Fixes gh-21542
This commit is contained in:
Madhura Bhave 2020-08-06 17:49:00 -07:00
parent ccffd50285
commit cdbb7f441a
3 changed files with 51 additions and 2 deletions

View File

@ -426,6 +426,11 @@ You can also supply the JSON as a JNDI variable, as follows: `java:comp/env/spri
====
NOTE: Although `null` values from the JSON will be added to the resulting property source, the `PropertySourcesPropertyResolver` treats `null` properties as missing values.
This means that the JSON cannot override properties from lower order property sources with a `null` value.
[[boot-features-external-config-random-values]]
=== Configuring Random Values

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
@ -38,6 +38,7 @@ import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.StandardServletEnvironment;
@ -123,9 +124,17 @@ public class SpringApplicationJsonEnvironmentPostProcessor implements Environmen
@SuppressWarnings("unchecked")
private void extract(String name, Map<String, Object> result, Object value) {
if (value instanceof Map) {
if (CollectionUtils.isEmpty((Map<?, ?>) value)) {
result.put(name, value);
return;
}
flatten(name, result, (Map<String, Object>) value);
}
else if (value instanceof Collection) {
if (CollectionUtils.isEmpty((Collection<?>) value)) {
result.put(name, value);
return;
}
int index = 0;
for (Object object : (Collection<Object>) value) {
extract(name + "[" + index + "]", result, object);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
@ -17,6 +17,7 @@
package org.springframework.boot.env;
import java.util.Collections;
import java.util.Map;
import org.junit.jupiter.api.Test;
@ -26,6 +27,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.mock.env.MockPropertySource;
import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.web.context.support.StandardServletEnvironment;
@ -170,6 +172,39 @@ class SpringApplicationJsonEnvironmentPostProcessorTests {
assertThat(this.environment.getPropertySources()).containsSequence(custom, json, servlet, jndi);
}
@Test
void nullValuesShouldBeAddedToPropertySource() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"SPRING_APPLICATION_JSON={\"foo\":null}");
this.processor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.containsProperty("foo")).isTrue();
}
@Test
void emptyValuesForCollectionShouldNotBeIgnored() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"SPRING_APPLICATION_JSON={\"foo\":[]}");
MockPropertySource source = new MockPropertySource();
source.setProperty("foo", "bar");
this.environment.getPropertySources().addLast(source);
assertThat(this.environment.resolvePlaceholders("${foo}")).isEqualTo("bar");
this.environment.getPropertySources().addLast(source);
this.processor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.resolvePlaceholders("${foo}")).isEmpty();
}
@Test
@SuppressWarnings("unchecked")
void emptyMapValuesShouldNotBeIgnored() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"SPRING_APPLICATION_JSON={\"foo\":{}}");
MockPropertySource source = new MockPropertySource();
source.setProperty("foo.baz", "bar");
this.environment.getPropertySources().addLast(source);
this.processor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.getProperty("foo", Map.class)).isEmpty();
}
private void testServletPropertySource(String servletPropertySourceName) {
this.environment.getPropertySources().addFirst(getPropertySource(servletPropertySourceName, "servlet"));
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,