Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -304,13 +304,32 @@ private boolean process(Map<String, Object> map, MatchCallback callback) {
* @since 4.1.3
*/
protected final Map<String, Object> getFlattenedMap(Map<String, Object> source) {
return getFlattenedMap(source, false);
}

/**
* Return a flattened version of the given map, recursively following any nested Map
* or Collection values. Entries from the resulting map retain the same order as the
* source. When called with the Map from a {@link MatchCallback} the result will
* contain the same values as the {@link MatchCallback} Properties.
* @param source the source map
* @param includeNulls if {@code null} entries can be included in the result
* @return a flattened map
* @since 7.0.4
*/
protected final Map<String, Object> getFlattenedMap(Map<String, Object> source, boolean includeNulls) {
Map<String, Object> result = new LinkedHashMap<>();
buildFlattenedMap(result, source, null);
buildFlattenedMap(result, source, null, includeNulls);
return result;
}

@SuppressWarnings({"rawtypes", "unchecked"})
private void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, @Nullable String path) {
private void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, @Nullable String path,
boolean includeNulls) {
if (includeNulls && source.isEmpty()) {
result.put(path, null);
return;
}
source.forEach((key, value) -> {
if (StringUtils.hasText(path)) {
if (key.startsWith("[")) {
Expand All @@ -325,7 +344,7 @@ private void buildFlattenedMap(Map<String, Object> result, Map<String, Object> s
}
else if (value instanceof Map map) {
// Need a compound key
buildFlattenedMap(result, map, key);
buildFlattenedMap(result, map, key, includeNulls);
}
else if (value instanceof Collection collection) {
// Need a compound key
Expand All @@ -336,7 +355,7 @@ else if (value instanceof Collection collection) {
int count = 0;
for (Object object : collection) {
buildFlattenedMap(result, Collections.singletonMap(
"[" + (count++) + "]", object), key);
"[" + (count++) + "]", object), key, includeNulls);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@
*/
class YamlProcessorTests {

private final YamlProcessor processor = new YamlProcessor() {
};
private final TestYamlProcessor processor = new TestYamlProcessor();


@Test
Expand Down Expand Up @@ -182,8 +181,33 @@ void customTypeNotSupportedDueToExplicitConfiguration() {
.withMessageContaining("Global tag is not allowed: tag:yaml.org,2002:java.net.URL");
}

@Test
void processAndFlattenWithoutIncludedNulls() {
setYaml("foo: bar\nbar:\n spam: {}");
Map<String, Object> flattened = this.processor.processAndFlatten(false);
assertThat(flattened).containsEntry("foo", "bar").doesNotContainKey("bar.spam").hasSize(1);
}

@Test
void processAndFlattenWithIncludedNulls() {
setYaml("foo: bar\nbar:\n spam: {}");
Map<String, Object> flattened = this.processor.processAndFlatten(true);
assertThat(flattened).containsEntry("foo", "bar").containsEntry("bar.spam", null).hasSize(2);
}

private void setYaml(String yaml) {
this.processor.setResources(new ByteArrayResource(yaml.getBytes()));
}

private static class TestYamlProcessor extends YamlProcessor {

Map<String, Object> processAndFlatten(boolean includeNulls) {
Map<String, Object> flattened = new LinkedHashMap<>();
process((properties, map) -> flattened.putAll(getFlattenedMap(map, includeNulls)));
return flattened;
}


}

}