Указание дополнительных аргументов для создания класса при десериализации JSON


Джексон имеет удобную функцию, которую вы можете указать пользовательские конструкторы или статические фабричные методы для использования при создании класса, получая параметры из объекта JSON. Однако я не уверен, что лучший способ-это передать дополнительный аргумент конструктора десериализованному объекту. Например, я хотел бы, чтобы Джексон использовал этот JSON для построения и инициализации следующего класса:

{
    "x": "foo",
    "y": "bar",
    "z": "baz"
}

public class Foo {
    /*
     * conf and x <b>must</b> be supplied at construction time
     */
    @JsonCreator
    public Foo(Configuration conf, @JsonValue("x") String x)

    public String getX();

    public String getY();
    public void setY(String y);
    public String getZ();
    public void setZ(String z);
}

public class SomeMainApplicationClass {
    public Foo loadFoo(InputStream in, Configuration conf) {
        ObjectMapper mapper = new ObjectMapper(/* ??? */);
        /* ??? */
        return mapper.readValue(in, Foo.class);
    }
}

Моим первым инстинктом было то, что я должен был создать некоторые вид объекта фабрики:

public class FooFactory {
    private final Configuration conf;
    public FooFactory(Configuration conf) {
        this.conf = conf;
    }
    @JsonCreator
    public createFoo(@JsonProperty("x") String x) {
        return new Foo(conf, x);
    }
}
Но у Джексона нет простого способа подключить это-большинство методов, которые я нашел (или варианты на основе аннотаций), используют статические методы фабрики.

Ответ не должен использовать глобальные / статические переменные-я хочу настроить объект конфигурации на per-ObjectMapper основа.

Мой предпочтительный ответ должен :

  • будьте кратки! Я знаю, что есть несколько способов подойти к этому, я ищу самый простой
  • продолжайте использовать способность Джексона использовать отражение и интерпретировать аннотации привязки данных для свойств, не являющихся конструкторами, вместо написания десериализатора, который должен обновляться каждый раз, когда я добавляю или редактирую настраиваемое свойство
    • не требует, чтобы я вручную считывал и буферизовал свойства объекта из JSON (т. е. не дублируйте BeanDeserializer._deserializeUsingPropertyBased)
  • работа с аннотацией mix-ins

Я исследовал создание пользовательских CreatorContainers или DeserializerProviders, но я еще не придумал метод, который бы отвечал моим требованиям.

1 2

1 ответ:

В настоящее время нет возможности сделать это; была бы "возможность вводить значения во время десериализации" (см. http://jira.codehaus.org/browse/JACKSON-406 ) сделать это? Вы можете спросить об этом в списке рассылки пользователя Jackson (или dev), так как это одна из наиболее приоритетных функций, которая, надеюсь, будет работать для Jackson 1.9.

Одна из возможностей заключается в том, чтобы просто использовать @JsonCreator, украсить все параметры с помощью @JsonParameter и получить оттуда значение доступа - если нет соответствующего свойства, вы получите null в качестве значения. Это не оптимально, но если вы можете получить доступ к нужному значению (через ThreadLocal, заполненный перед вызовом десериализации), вы, по крайней мере, сможете решить эту проблему.