通用树的自定义 Jackson 序列化程序

2022-09-03 02:35:37

假设我有一个在Java中实现的参数化树,如下所示:

public class Tree<E> {
   private static class Node {
      E element;
      List<Node> children.
   }

   Node root;

   //... You get the idea.
}

这里的想法是,上面的实现只关注树的拓扑,但对将通过实例化存储在树中的元素一无所知。

现在,假设我希望我的树元素是地理区域。它们被组织成树的原因是因为大陆包含国家,国家包含州或省,等等。为简单起见,地理区域具有名称和类型:

public class GeoElement { String name; String type; }

因此,最后,地理层次结构如下所示:

public class Geography extends Tree<GeoElement> {}

现在到杰克逊序列化。假设 Jackson 序列化程序可以看到这些字段,则此实现的直接序列化将如下所示:

{
   "root": {
      "element": {
         "name":"Latin America",
         "type":"Continent"
      }
      "children": [
          {
             "element": {
                "name":"Brazil",
                "type":"Country"
             },
             "children": [
                 // ... A list of states in Brazil
             ]
          },
          {
             "element": {
                "name":"Argentina",
                "type":"Country"
             },
             "children": [
                 // ... A list of states in Argentina
             ]
          }
      ]
   }

这种JSON渲染并不好,因为它包含来自树和Node类的不必要的工件,即“根”和“元素”。相反,我需要的是这个:

{
   "name":"Latin America",
   "type":"Continent"
   "children": [
       {
          "name":"Brazil",
          "type":"Country"
          "children": [
             // ... A list of states in Brazil
          ]
       },
       {
          "name":"Argentina",
          "type":"Country"
          "children": [
             // ... A list of states in Argentina
          ]
       }
   ]
}

任何帮助都是最值得赞赏的。-伊戈尔。


答案 1

你需要的是@JsonUnwrapped

用于指示属性应序列化为“未包装”的注释;也就是说,如果它将被序列化为 JSON 对象,则其属性将作为其包含对象的属性包含在内。

将此注释添加到类的字段 & 字段,如下所示:rootTreeelementNode

public class Tree<E> {
   private static class Node {

      @JsonUnwrapped
      E element;
      List<Node> children.
   }

   @JsonUnwrapped
   Node root;

   //... You get the idea.
}

它将为您提供所需的输出:

{
    "name": "Latin America",
    "type": "Continent",
    "children": [{
        "name": "Brazil",
        "type": "Country",
        "children": []
    }, {
        "name": "Argentina",
        "type": "Country",
        "children": []
    }]
}

答案 2

也许可以这样使用:@JsonValue

public class Tree<E> {
  @JsonValue
  Node root;
}

如果你所需要的只是“打开”你的树?