Подтвердить что ты не робот

Сериализация универсального 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?

4b9b3361

Ответ 1

По умолчанию Джексон будет сериализоваться с помощью методов get. Как только он попадает в метод getAsJson, poom, бесконечный цикл. Отметьте его аннотацией @JsonIgnore.

@JsonIgnore
public String getAsJSON() {
    ObjectMapper mapper = new ObjectMapper();
    return mapper.writeValueAsString(this) ; 
}

Вы также можете настроить Jackson на сериализацию только на основе свойств, что может устранить необходимость в @JsonIgnore, но это может или не может удовлетворить ваши потребности.

Я считаю, что последний Джексон позволяет использовать аннотацию Hibernate @Transient, хотя я не уверен, как ее настроить (недавнее изменение).

Ответ 2

Как и другие, это, скорее всего, связано с циклическими ссылками; по умолчанию Джексон не обрабатывает такие зависимости.

Вы можете либо попробовать пропустить сериализацию этого свойства, либо, если он связан с родительским/дочерним типом, аннотировать его как таковой (см. " двунаправленные ссылки" в Вики-версии Jackson для более подробной информации).

Для чего это стоит, общие типы не вызывают этого (то есть, вероятно, это просто совпадение здесь); циклические типы прекрасно подходят.