[英]Deserialize YAML map of POJOs with Jackson where Map keys are an object field
給定 class:
@Data
class Widget {
String name;
int price;
}
以及以下 yaml 文件:
Widget1:
price: 5
Widget2:
price: 6
Widget3:
price: 7
使用 Jackson 我想將其反序列化為Map<String, Widget>
,其中小部件名稱字段設置為相應的 map 鍵。 以下代碼段有效,但缺點是阻止使用不可變的 object 類型,例如@Value
。 我考慮的另一個不優雅的解決方案是創建一個單獨的不可變WidgetWithName
class,它是在 jackson 反序列化之后構建的。 如果有人可以提出更好的方法,那將很有趣。
Map<String, Widget> getWidgets(String yaml) throws Exception {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
TypeFactory typeFactory = mapper.getTypeFactory();
MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, Widget.class);
map = mapper.readValue(yaml, mapType);
map.forEach((k, v) -> v.setName(k); // so much for immutability
return map
}
Jackson will not help you because it is a generalization over YAML and JSON (and XML or so I heard) and therefore provides less functionality than directly using SnakeYAML.
使用 SnakeYAML,理論上您可以使用自定義構造函數來實現這一點,但它需要大量關於反序列化過程的知識,因為 YAML 並非旨在將不同級別的節點合並為一個值。
坦率地說,擁有一個單獨的 class 是迄今為止最簡單和最好的可維護解決方案。 一個單獨的 class 名為WidgetBuilder
,只有price
字段和 function Widget finish(String name)
將允許您
return map.entrySet().stream().map((k, v) -> v.finish(k)).collect(
Collectors.toMap(Widget::getName, Function.identity()));
這似乎足夠優雅。 (如果您不再需要 map,您可以收集到一個列表。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.