我想使用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
值返回给Jackson会导致错误的行为。我相信我可以通过向所有类添加公共toJson()
方法来解决此问题。该方法将返回Map<String, JsonNode>
,其中,对于简单字段,该值是一个字符串节点;对于复杂字段,该值是toJson()
的输出。不幸的是,这将污染我的公共API的实现细节。
如何在不污染类的公共API的情况下实现所需的行为?
更新:我刚刚在https://stackoverflow.com/a/9599585/14731看到了一个有趣的答案……也许我可以将复杂字段的String值转换回JsonNode
,然后再将它们传递给Jackson
答案 0 :(得分:0)
我认为您应该在每个类中实现两种方法-一种用于转储数据,第二种用于从原始数据结构构建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());
}
}