在序列化中注入其他字段

时间:2014-01-03 15:49:18

标签: java json angularjs rest jackson

我有使用Jackson序列化的对象。 e.g。

class A {
    int id;
    String value
}

被序列化为:

{
    "id": 1,
    "value": "test"
}

现在我想要序列化版本中的附加字段

{
    "id": 1,
    "value": "test"
    "__errors__": [
        { field: "id", "message": "already in use" },
        { field: "value", "message": "field to long" },
    ]
}

此字段由类Error:

列表组成
class Error {
    String field;
    String message;
}

这应该在序列化工作时完成,而无需向A类添加方法/属性

那么有没有办法其他字段注入杰克逊映射器? Best是一种通用方法,可以在没有附加代码的情况下传递给映射器的所有类。

(背景:我想使用它在正常结果中将验证错误返回给AngularJS。因为将两者都放在容器中会使客户端的代码复杂化。)

提前致谢!

编辑:

想象最终用法看起来像这样:

ObjectMapper mapper = ...;
PrintWriter out = ...;

// Normally the parsed user input
A a = new A( 5, "test" );

// Normally generated by validation of user input
List<Error> errors = Arrays.asList( new Error( "id", "already in use" ) );

// No write it as combined json
mapper.writeValue( out, a, error );
// ... or ...
customWrite( out, a, error );

EDIT2:

目前我正在寻找两种可能的解决方案:

  1. 编写自定义序列化程序。看起来像一个干净的解决方案,但需要做默认序列化程序所做的所有事情。但这是一个复杂的解决方案,因为我首先要弄清楚自定义序列化和扩展默认是如何工作的。
  2. 只需使用字符串替换和连接。单独写两个对象并删除凝视/闭合花括号并将其附加在另一个上。快,但很脏。 (我真的不喜欢这个,但它可以工作。)

1 个答案:

答案 0 :(得分:3)

您可以使用ObjectMapper.convertValue方法轻松完成此操作。见下面的例子:

A a = new A(101, "test");
List<Error> errors = Arrays.asList(new Error("id", "already in use"), new Error("value",
        "field to long"));

// Create Jackson objects
ObjectMapper jsonMapper = new ObjectMapper();
MapType mapType = jsonMapper.getTypeFactory().constructMapType(LinkedHashMap.class,
        String.class, Object.class);

// Create map
LinkedHashMap<String, Object> map = jsonMapper.convertValue(a, mapType);
map.put("__errors__", errors);

// Serialize map
String json = jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(map);

System.out.println(json);

以上示例打印:

{
  "id" : 101,
  "value" : "test",
  "__errors__" : [ {
    "field" : "id",
    "message" : "already in use"
  }, {
    "field" : "value",
    "message" : "field to long"
  } ]
}