Retain YAML property ordering
Update YamlPropertySourceLoader to use a MapPropertySource rather than a PropertiesPropertySource to ensure that the underlying order is retained. Fixes gh-2022
This commit is contained in:
parent
6c96608b11
commit
39ee583977
|
|
@ -17,11 +17,14 @@
|
||||||
package org.springframework.boot.env;
|
package org.springframework.boot.env;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.YamlProcessor;
|
||||||
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
||||||
import org.springframework.boot.yaml.SpringProfileDocumentMatcher;
|
import org.springframework.boot.yaml.SpringProfileDocumentMatcher;
|
||||||
import org.springframework.core.env.PropertiesPropertySource;
|
import org.springframework.core.env.MapPropertySource;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
@ -43,22 +46,44 @@ public class YamlPropertySourceLoader implements PropertySourceLoader {
|
||||||
public PropertySource<?> load(String name, Resource resource, String profile)
|
public PropertySource<?> load(String name, Resource resource, String profile)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
|
if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
Processor processor = new Processor(resource, profile);
|
||||||
if (profile == null) {
|
Map<String, Object> source = processor.process();
|
||||||
factory.setMatchDefault(true);
|
if (!source.isEmpty()) {
|
||||||
factory.setDocumentMatchers(new SpringProfileDocumentMatcher());
|
return new MapPropertySource(name, source);
|
||||||
}
|
|
||||||
else {
|
|
||||||
factory.setMatchDefault(false);
|
|
||||||
factory.setDocumentMatchers(new SpringProfileDocumentMatcher(profile));
|
|
||||||
}
|
|
||||||
factory.setResources(new Resource[] { resource });
|
|
||||||
Properties properties = factory.getObject();
|
|
||||||
if (!properties.isEmpty()) {
|
|
||||||
return new PropertiesPropertySource(name, properties);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link YamlProcessor} to create a {@link Map} containing the property values.
|
||||||
|
* Similar to {@link YamlPropertiesFactoryBean} but retains the order of entries.
|
||||||
|
*/
|
||||||
|
private static class Processor extends YamlProcessor {
|
||||||
|
|
||||||
|
public Processor(Resource resource, String profile) {
|
||||||
|
if (profile == null) {
|
||||||
|
setMatchDefault(true);
|
||||||
|
setDocumentMatchers(new SpringProfileDocumentMatcher());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setMatchDefault(false);
|
||||||
|
setDocumentMatchers(new SpringProfileDocumentMatcher(profile));
|
||||||
|
}
|
||||||
|
setResources(new Resource[] { resource });
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> process() {
|
||||||
|
final Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||||
|
process(new MatchCallback() {
|
||||||
|
@Override
|
||||||
|
public void process(Properties properties, Map<String, Object> map) {
|
||||||
|
result.putAll(map);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return getFlattenedMap(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,24 @@
|
||||||
|
|
||||||
package org.springframework.boot.env;
|
package org.springframework.boot.env;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.core.env.EnumerablePropertySource;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link YamlPropertySourceLoader}.
|
* Tests for {@link YamlPropertySourceLoader}.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
public class YamlPropertySourceLoaderTests {
|
public class YamlPropertySourceLoaderTests {
|
||||||
|
|
||||||
|
|
@ -40,4 +47,18 @@ public class YamlPropertySourceLoaderTests {
|
||||||
assertEquals("spam", source.getProperty("foo.bar"));
|
assertEquals("spam", source.getProperty("foo.bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void orderedItems() throws Exception {
|
||||||
|
StringBuilder yaml = new StringBuilder();
|
||||||
|
List<String> expected = new ArrayList<String>();
|
||||||
|
for (char c = 'a'; c <= 'z'; c++) {
|
||||||
|
yaml.append(c + ": value" + c + "\n");
|
||||||
|
expected.add(String.valueOf(c));
|
||||||
|
}
|
||||||
|
ByteArrayResource resource = new ByteArrayResource(yaml.toString().getBytes());
|
||||||
|
EnumerablePropertySource<?> source = (EnumerablePropertySource<?>) this.loader
|
||||||
|
.load("resource", resource, null);
|
||||||
|
assertNotNull(source);
|
||||||
|
assertThat(source.getPropertyNames(), equalTo(expected.toArray(new String[] {})));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue