Используйте @JacksonInject с @JsonCreator на карте верхнего уровня

С помощью библиотеки Jackson json можно десериализовать объект с помощью @JsonCreator и получить карту «верхнего уровня», представляющую входной json, как показано ниже:

class MyClass {
    final int field;

    @JsonCreator
    public MyClass(Map map) {
        this.field = (int) map.get("theInt");
    }
}

или даже на статическом заводском методе:

class MyClass {
    final int field;

    public MyClass(int theInt) {
        this.field = theInt;
    }

    @JsonCreator
    static MyClass create(Map map) {
        return new MyClass((int) map.get("theInt"));
    }
}

Предыдущие примеры могут обрабатывать следующий тип ввода json:

{
    "key1":"value1",
    "key2":"value2",
    "key3":"value3"
}

Это особенно полезно в моем случае, потому что я хотел бы десериализовать json, структура которого мне неизвестна. Получение доступа к тому, что я называю «картой верхнего уровня», упрощает работу.

Я хотел бы десериализовать свои объекты таким образом, поскольку он также позволяет создавать неизменяемые объекты вместо использования @JsonAnySetter , что не позволяет этого, и @JsonProperty , которое я не могу использовать, так как я не знаю заранее имя свойства, как я упоминал ранее.

Затем, чтобы пойти дальше, я хотел бы добавить некоторую конфигурацию в свой фабричный метод, и Джексон позволяет это с помощью @JacksonInject и вызова withInjectableValues ​​(InjectableValues) на ObjectMapper .

В конечном итоге я хотел бы использовать именно такой код:

class MyClass {
    final MyField[] myFields;

    public MyClass(MyField... myFields) {
        this.myFields = myFields;
    }

    @JsonCreator
    static MyClass create(@JacksonInject("conf") Conf conf, Map map) {
        MyFields[] myFields;
        // initialize myFields (or any other object) based on the content of map
        // and also make use of the inject conf
        return new MyClass(myFields);
    }
}

К сожалению, Джексон выдает следующие исключения:

  • при попытке трюка с конструктором

JsonMappingException: аргумент № 1 конструктора [ конструктор MyClass, аннотации: {JsonCreator = @ JsonCreator ()}] не имеет аннотации имени свойства; должен иметь имя, если конструктор с несколькими параметрами, аннотированный как Creator

  • , при попытке трюка с фабричным методом

JsonMappingException: аргумент № 1 фабричного метода [создание метода, аннотации: {JsonCreator = @ JsonCreator ()}] не имеет аннотация имени свойства; должен иметь, когда статический метод с несколькими параметрами, помеченный как Creator

Кто-нибудь знает, как я могу решить проблему?

Чтобы подвести итог требований, мне нужно:

  • доступ к карте верхнего уровня (не знаю имена свойств json заранее)
  • для создания неизменяемого объекта (поэтому нельзя использовать @JsonAnySetter )
  • для добавления некоторой конфигурации в декорированный конструктор @JsonCreator или фабричный метод

Я не могу изменить входной формат json, который выглядит следующим образом:

{
    "key1":"value1",
    "key2":"value2",
    "key3":"value3"
}

[EDIT]

Это известная проблема: http://jira.codehaus.org/browse/JACKSON-711 (еще не исправлена)

6
задан killy971 2 December 2011 в 00:27
поделиться