Мне пришлось обработать некоторый JSON, который мог прийти в несколько разных форматах (и где мне нужно было только подмножество данных JSON), и я использовал JsonPointer (от Джексона), чтобы запросить JSON. Я написал нефункциональное решение проблемы, которое сработало для меня, но я хотел попробовать функциональный подход для целей обучения. В тестовой программе ниже вы можете увидеть мои два решения. Они оба работают, но функциональное решение стало довольно многословным, и я получил досадное предупреждение от Intellij относительно использования get () без проверки isPresent. Я хотел бы видеть предложения по улучшению функциональной реализации, и я счастлив видеть решения, использующие сторонние библиотеки. Я полагаю, что основная проблема здесь заключается в том, как моделировать if-else-if-else, где каждая ветвь должна возвращать какое-то значение функциональным способом.
@Test
public void testIt() {
ObjectMapper om = new ObjectMapper();
ImmutableList.of(
"{ \"foo\": { \"key\": \"1\" } }",
"{ \"bar\": { \"key\": \"1\" } }",
"{ \"key\": \"1\" }")
.forEach(str -> {
try {
System.out.println("Non-functional: " + getNode(om.readTree(str)));
System.out.println("Functional: " + getNodeFunc(om.readTree(str)));
} catch (Exception e) {
throw new RuntimeException("", e);
}
});
}
private JsonNode getNode(JsonNode parentNode) {
JsonPointer jp1 = JsonPointer.compile("/foo");
JsonPointer jp2 = JsonPointer.compile("/bar");
if (!parentNode.at(jp1).isMissingNode()) {
return parentNode.at(jp1);
} else if (!parentNode.at(jp2).isMissingNode()) {
return parentNode.at(jp2);
}
return parentNode;
}
private JsonNode getNodeFunc(JsonNode parentNode) {
BiFunction<JsonNode, String, Optional<JsonNode>> findNode = (node, path) -> {
JsonPointer jp = JsonPointer.compile(path);
return node.at(jp).isMissingNode() ? Optional.empty() : Optional.of(node.at(jp));
};
return findNode.apply(parentNode, "/foo")
.map(Optional::of)
.orElseGet(() -> findNode.apply(parentNode, "/bar"))
.map(Optional::of)
.orElse(Optional.of(parentNode))
.get(); // Intellij complains here: Optional.get() without isPresent check
}