Сериализация универсального Java-объекта JSON с использованием Jackson
Когда я попытался преобразовать следующий экземпляр класса в JSON (используя Джексон)
public class RPCRespond<Result> {
private int code;
private Result result;
private boolean success;
private String failureReason;
public RPCRespond() {
this.code = 0;
this.success = true;
this.result = null;
}
public RPCRespond(Result result) {
this.code = 0;
this.success = true;
this.result = result;
}
public RPCRespond(int code, String failureReason) {
this.code = code;
this.success = false;
this.failureReason = failureReason;
}
public RPCRespond(int code, String failureReason, Object... args) {
this.code = code;
this.success = false;
this.failureReason = String.format(failureReason, args);
}
public Result getResult() {
return result;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getFailureReason() {
return failureReason;
}
public void setFailureReason(String failureReason) {
this.failureReason = failureReason;
}
public int getCode() {
return code;
}
public boolean getSuccess() {
return success;
}
@Transient
public String getAsJSON() {
String json = "";
ObjectMapper mapper = new ObjectMapper();
json = mapper.writeValueAsString(this) ;
return json ;
}
}
он попадает в бесконечный цикл:
at sun.reflect.GeneratedMethodAccessor48.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601) at
org.codehaus.jackson.map.ser.BeanPropertyWriter.get(BeanPropertyWriter.java:483)
at
org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:418)
at
org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
at
org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
at
org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)
at
org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
at
org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2566)
at
org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2088)
Начало RPCRespond выполняется
User u = new User() ;
u.setFirstName("aaaa") ;
RPCRespond<User> result = new RPCRespond<User>(u) ;
result.setSuccess(true) ;
return result.getAsJSON() ;
Как преобразовать RPCRespond в JSON?
Ответы
Ответ 1
По умолчанию Джексон будет сериализоваться с помощью методов get
. Как только он попадает в метод getAsJson
, poom, бесконечный цикл. Отметьте его аннотацией @JsonIgnore
.
@JsonIgnore
public String getAsJSON() {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(this) ;
}
Вы также можете настроить Jackson на сериализацию только на основе свойств, что может устранить необходимость в @JsonIgnore
, но это может или не может удовлетворить ваши потребности.
Я считаю, что последний Джексон позволяет использовать аннотацию Hibernate @Transient
, хотя я не уверен, как ее настроить (недавнее изменение).
Ответ 2
Как и другие, это, скорее всего, связано с циклическими ссылками; по умолчанию Джексон не обрабатывает такие зависимости.
Вы можете либо попробовать пропустить сериализацию этого свойства, либо, если он связан с родительским/дочерним типом, аннотировать его как таковой (см. " двунаправленные ссылки" в Вики-версии Jackson для более подробной информации).
Для чего это стоит, общие типы не вызывают этого (то есть, вероятно, это просто совпадение здесь); циклические типы прекрасно подходят.