Вероятно, вы должны пойти с лямбдой ради удобочитаемости. Но как интересное исследование функций более высокого порядка, вот расширенная версия q-combinator в Python (также известная как компилятор странных птиц). Это позволяет вам создать новую функцию, составив две функции
def compose(inner_func, *outer_funcs):
if not outer_funcs:
return inner_func
outer_func = compose(*outer_funcs)
return lambda *args, **kwargs: outer_func(inner_func(*args, **kwargs))
from operator import itemgetter, methodcaller
name_lowered = compose(itemgetter('name'), methodcaller('lower'))
print(name_lowered( {'name': 'Foo'} ))
. Если вы измените определения внутреннего и внешнего в функции compose
, вы получите более традиционный b-combinator (bluebird). Мне больше нравится q-combinator из-за сходства с Unix-каналами.
Я не думаю, что такой простой способ существует, потому что CollectionDeserializer
создает экземпляр коллекции перед анализом. Так что для этого вам нужно создать свой десериализатор.
Но я не уверен =))
Общее решение - использовать пользовательский модуль. Вы можете определить классы, которые вы хотели бы использовать для коллекций. Для Гуавы есть модуль Maven:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-guava</artifactId>
<version>x.y.z</version>
</dependency>
Теперь вы можете зарегистрировать свой новый модуль:
ObjectMapper mapper = new ObjectMapper();
// register module with object mapper
mapper.registerModule(new GuavaModule());
Теперь вы можете указать в своем POJO
, что вы хотите иметь неизменяемый выполнение списка.
class Pojo {
private ImmutableList<Integer> ints;
public ImmutableList<Integer> getInts() {
return ints;
}
public void setInts(ImmutableList<Integer> ints) {
this.ints = ints;
}
@Override
public String toString() {
return "Pojo{" +
"ints=" + ints + " " + ints.getClass() + '}';
}
}
и ниже пример:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new GuavaModule());
String json = "{\"ints\":[1,2,3,4]}";
System.out.println(mapper.readValue(json, Pojo.class));
печатает:
Pojo{ints=[1, 2, 3, 4] class com.google.common.collect.RegularImmutableList}
Если вы не хотите связывать свои классы POJO
с реализацией List
, вам нужно добавьте дополнительную конфигурацию, используя класс SimpleModule
. Итак, ваш POJO
выглядит следующим образом:
class Pojo {
private List<Integer> ints;
public List<Integer> getInts() {
return ints;
}
public void setInts(List<Integer> ints) {
this.ints = ints;
}
@Override
public String toString() {
return "Pojo{" +
"ints=" + ints + " " + ints.getClass() + '}';
}
}
, а ваш пример выглядит следующим образом:
SimpleModule useImmutableList = new SimpleModule("UseImmutableList");
useImmutableList.addAbstractTypeMapping(List.class, ImmutableList.class);
GuavaModule module = new GuavaModule();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
mapper.registerModule(useImmutableList);
String json = "{\"ints\":[1,2,3,4]}";
System.out.println(mapper.readValue(json, Pojo.class));
Выше кода печатается:
Pojo{ints=[1, 2, 3, 4] class com.google.common.collect.RegularImmutableList}
Когда вы удалите лишние SimpleModule
отпечатки кода выше:
Pojo{ints=[1, 2, 3, 4] class java.util.ArrayList}
Я не вижу смысла использовать Collections.emptyList()
, если он пуст. Модуль Guava
использует RegularImmutableList
для непустых и пустых массивов.
Для преобразования null -> empty
см. Этот вопрос:
, но я рекомендуем установить его на empty
в POJO
, как показано ниже:
private List<Integer> ints = Collections.emptyList();