Сериализация универсального объекта Java в JSON с использованием Jackson

#java #jackson

#java #джексон

Вопрос:

Когда я попытался преобразовать следующий экземпляр класса в JSON (используя Jackson)

 public class RPCRespond<Result> {

    private int code;
    private Result resu<
    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 = resu<
    }

    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 resu<
    }


    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 ;
    }

}
  

он попадает в бесконечный цикл:

 в sun.reflect.Созданный methodaccessor48.invoke (неизвестный источник) в 
 sun.reflect.Делегирование METHODACCESSORIMPL.invoke(делегирование methodaccessorimpl.java:43) 
 в java.lang.reflect.Метод.invoke(Method.java:601) в 
 org.codehaus.jackson.map.ser.BeanPropertyWriter.get(BeanPropertyWriter.java:483) 
в 
 org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:418) 
в 
 org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
 в 
 org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
 в 
 org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610) 
в 
 org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
 в 
 org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2566)
 в 
 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. Совершенно не связано, но подписи ctor оставляют меня немного равнодушным — я бы предпочел видеть маленькие фабрики, которые явно называют статус успеха / неудачи, а не ctor с жуткой семантикой. Также не уверен, почему вы установили строку пустой, а затем немедленно перезаписали ее с помощью JSON.

2. Я удалил некоторый код для простоты вопроса

3. Вы пробовали использовать @JsonIgnore аннотацию? Я не знаю, пропустит ли он @Transient properties по умолчанию. Является ли это объектом Hibernate?

4. пользователь — это объект pojo, у которого пока нет аннотаций гибернации. Я планирую добавить их позже. куда вы предлагаете добавить @jsonignore?

5. Для получателя, который, вероятно, вызывает бесконечный цикл.

Ответ №1:

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

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

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

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

Ответ №2:

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

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

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

Комментарии:

1. ВЫ, СЭР, МОЙ ГЕРОЙ. Сохранено 0,5 П.Д.