Jackson IOException: не удается десериализовать класс com.mycompany.models.Person $Address (тип нестатического класса членов) как Bean

У меня есть класс, который выглядит так:

public class Person {
    public class Address {
        private String line1;
        private String line2;
        private String zipCode;
        private String state;

        // standard public getters and setters for the class here
   }

private String name;
private String address;

// standard public getters and setters for the class here

}

и heres, как я использую джексон с ним.

public class JsonTest {
    public static <T> Object fromJson(String jsonAsString, Class<T> pojoClass)
throws JsonMappingException, JsonParseException, IOException {
        return m.readValue(jsonAsString, pojoClass);
    }

    public static String toJson(Object pojo, boolean prettyPrint)
throws JsonMappingException, JsonGenerationException, IOException {
        StringWriter sw = new StringWriter();
        JsonGenerator jg = jf.createJsonGenerator(sw);
        if (prettyPrint) {
            jg.useDefaultPrettyPrinter();
        }
        m.writeValue(jg, pojo);
        return sw.toString();
    }

    public static void main(String[] args) {
         Person p = new Person();
         String json = this.toJson(p, true); // converts ‘p’ to JSON just fine
         Person personFromJson = this.fromJson(json, Person.class); // throws exception!!!
    }
}

3-я строка основного метода (где я пытаюсь преобразовать json в объект Person), выдает это исключение:

IOException: Can not deserialize Class com.mycompany.models.Person$Address (of type non-static member class) as a Bean

что я делаю неправильно?

Ответ 1

Поскольку внутренние классы не имеют конструктора с нулевым аргументом по умолчанию (у них есть скрытая ссылка на внешний/родительский класс), Джексон не может их создать.

Решение состоит в том, чтобы использовать внутренние классы static:

public class Outer {
    static class Inner {
        private String foo;
        public String getFoo() { return foo; }
    }
}

Оригинальный ответ:

Есть некоторые проблемы в реализации, и кажется, что вы не можете сериализовать такие классы, см. cowtowncoder для деталей.

Ответ 2

Правильно, это было то, что вы не можете сделать с текущими версиями Джексона (1.8 и ранее). Но абсолютно необходимо, чтобы внутренний класс был нестационарным? Если нет, просто добавьте "статический" в объявление адреса, и он будет работать нормально; проблема заключается в "скрытом" этом указателе, который нестатические внутренние классы принимают через конструктор.

Jackson 1.9 фактически поддерживает десериализацию простых применений нестатических внутренних классов, см. эту запись в Jira.