Schema mapping with Java functional interfaces
Mapping one data structure into another is a never ending chore since COBOL's MOVE CORRESPONDING
. One to one mappings are trivial, onnce computation is needed, clean code can become messy, really fast
Map with Functions
We will use the following, simplified, scenario with source and target formats:
{
"FirstName" : "Peter",
"LastName" : "Pan",
"DoB" : "1873-11-23",
"ToC" : "accepted",
"Marketing" : "no"
}
Desired Result:
{
"fullname" : "Peter Pan",
"birthday" : "1873-11-23",
"gdpr" : true
}
In our case only DoB
has a simple mapping to birthday
all others need computation or are dropped. So to keep code clean we will use a map with mapping functions, so each computation can be in its own method. The defaults 1:1 and drop functions get defined first.
final Map<String, Function<JsonObject, JsonObject>> functionList = new HashMap<>();
Function<JsonObject, JsonObject> simple(final String fieldNameIn, final String fieldNameOut) {
return in -> new JsonObject().put(fieldNameOut, in.getValue(fieldNameIn));
}
Function<JsonObject, JsonObject> drop() {
return in -> new JsonObject();
}
Each of the functions returns an Json object that only returns a value for the one field it gets called for. We will use a collector to aggregate the values. Since we are planning to use streams and functional interfaces, we need a helper class.
class MapHelper() {
JsonObject source;
Function<JsonObject, JsonObject> mapper;
JsonObject apply() {
return this.mapper.apply(this.source);
}
}
MapHelper getMapHelper(final JsonObject source, final Map.Entry<String, Object> incoming) {
MapHelper result = new MapHelper();
result.source = source;
result.mapper = this.functionList.getOrDefault(incoming.getKey(), drop());
return result;
}
Since each function will return some JSON, that needs to be merged together, we use a Java Collector to accumulate the values
Read more
Posted by Stephan H Wissel on 28 November 2020 | Comments (0) | categories: Java