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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlProcessor;
|
||||
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
||||
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.io.Resource;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
|
@ -43,22 +46,44 @@ public class YamlPropertySourceLoader implements PropertySourceLoader {
|
|||
public PropertySource<?> load(String name, Resource resource, String profile)
|
||||
throws IOException {
|
||||
if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
if (profile == null) {
|
||||
factory.setMatchDefault(true);
|
||||
factory.setDocumentMatchers(new SpringProfileDocumentMatcher());
|
||||
}
|
||||
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);
|
||||
Processor processor = new Processor(resource, profile);
|
||||
Map<String, Object> source = processor.process();
|
||||
if (!source.isEmpty()) {
|
||||
return new MapPropertySource(name, source);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link YamlPropertySourceLoader}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class YamlPropertySourceLoaderTests {
|
||||
|
||||
|
|
@ -40,4 +47,18 @@ public class YamlPropertySourceLoaderTests {
|
|||
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