我想使用 Jackson 来实现toString()
以返回对象的 JSON 表示形式,但我不想在我的代码中使用任何 Jackson 注释。
我尝试了如下方式的实现:
public String toString()
{
Map<String,Object> ordered = ImmutableMap.<String, Object>builder().
put("createdAt", createdAt.toString()).
put("address", address.toString()).
build();
ObjectMapper om = new ObjectMapper();
om.enable(SerializationFeature.INDENT_OUTPUT);
try
{
return om.writeValueAsString(object);
}
catch (JsonProcessingException e)
{
// Unexpected
throw new AssertionError(e);
}
}
这适用于简单字段,但如果"地址"有自己的字段,则不要得到这个:
{
"address" : {
"value" : "AZ4RPBb1kSkH4RNewi4NXNkBu7BX9DmecJ",
"tag" : null
}
我得到这个输出:
{
"address" : "{n"value" : "AZ4RPBb1kSkH4RNewi4NXNkBu7BX9DmecJ",n "tag" : null"
}
换句话说,地址值被视为字符串而不是JsonNode
。
澄清一下:
- 一方面,我想控制如何将简单的类字段转换为字符串。我不想使用杰克逊的内置转换器。
- 另一方面,对于复杂字段,将
String
值返回给杰克逊会导致错误的行为。
我相信我可以通过向所有类添加公共toJson()
方法来解决此问题。该方法将返回一个Map<String, JsonNode>
,其中值是简单字段的字符串节点和复杂字段的toJson()
输出。不幸的是,这会用实现细节污染我的公共 API。
如何在不污染类的公共 API 的情况下实现所需的行为?
更新:我刚刚在 https://stackoverflow.com/a/9599585/14731 看到了一个有趣的答案......也许我可以将复杂字段的字符串值转换回JsonNode
,然后再将它们传递给杰克逊。
我认为您应该在每个类中实现两种方法 - 一种用于转储数据,另一种用于从原始数据结构构建 JSON。你需要把它分开,否则每次封装嵌套的toString()
调用时,你都会把它嵌套得越来越深。
举个例子:
class Address {
private BigDecimal yourField;
/* …cut… */
public Map<String, Object> toMap() {
Map<String, Object> raw = new HashMap<>();
raw.put("yourField", this.yourField.toPlainString());
/* more fields */
return raw;
}
@Override
public String toString() {
// add JSON processing exception handling, dropped for readability
return new ObjectMapper().writeValueAsString(this.toMap());
}
}
class Employee {
private Address address;
/* …cut… */
public Map<String, Object> toMap() {
Map<String, Object> raw = new HashMap<>();
raw.put("address", this.address.toMap());
/* more fields */
return raw;
}
@Override
public String toString() {
// add JSON processing exception handling, dropped for readability
return new ObjectMapper().writeValueAsString(this.toMap());
}
}