I would like to flatten a HashMap instance like in this example. Note that the data is not in JSON format, this is just a pseudo code:
nested = {
"one": {
"two": {
"2a": "x",
"2b": "y"
}
},
"side": "value"
}
// output: { "one.two.2a": "x", "one.two.2b": "y", "side": "value" }
Unfortunately, I couldn't find any reference implementation for that so I came up with my recursive solution shown below. Is there a better way (in terms of not using recursion or performance or safety or cleanliness :)) to achieve this? The output should be another HashMap in flattened form.
I will use the result for this kind of purpose https://redislabs.com/redis-best-practices/data-storage-patterns/object-hash-storage/
public class Flat {
public static void flatten(Map<String, ?> target, Map<String, String> result, String path) {
for (var entry : target.entrySet()) {
var next = path.equals("") ? entry.getKey() : path + "." + entry.getKey();
if (entry.getValue() instanceof Map) {
flatten((Map) entry.getValue(), result, next);
} else {
result.put(next, entry.getValue().toString());
}
}
}
public static Map unflatten(Map<String, String> target) {
var result = new HashMap<String, Object>();
for (var entry : target.entrySet()) {
if (entry.getKey().split(".").length == 1) {
result.put(entry.getKey(), entry.getValue());
} else {
var path = entry.getKey().split(".");
Map<String, Object> current = new HashMap<>();
for (var i = 0; i < path.length - 1; i++) {
if (result.containsKey(path[i])) {
current = (Map) (result.get(path[i]));
} else {
current = new HashMap<>();
result.put(path[i], current);
}
}
current.put(path[path.length - 1], entry.getValue());
}
}
return result;
}
}