Я экспериментирую в сочетании Джексона и Ломбока. Это мои занятия:
package testelombok;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Value;
import lombok.experimental.Wither;
@Value
@Wither
@AllArgsConstructor(onConstructor=@__(@JsonCreator))
public class TestFoo {
@JsonProperty("xoom")
private String x;
private int z;
}
package testelombok;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xebia.jacksonlombok.JacksonLombokAnnotationIntrospector;
import java.io.IOException;
public class TestLombok {
public static void main(String[] args) throws IOException {
TestFoo tf = new TestFoo("a", 5);
System.out.println(tf.withX("b"));
ObjectMapper om = new ObjectMapper().setAnnotationIntrospector(new JacksonLombokAnnotationIntrospector());
System.out.println(om.writeValueAsString(tf));
TestFoo tf2 = om.readValue(om.writeValueAsString(tf), TestFoo.class);
System.out.println(tf2);
}
}
Это JAR-файлы, которые я добавляю в classpth:
Ломбок: https://projectlombok.org/downloads/lombok.jar (версия 1.16.10)
Аннотации Джексона: http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.8.2/jackson-annotations-2.8.2.jar
Ядро Джексона: http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.8.2/jackson-core-2.8.2.jar
Индикация данных Джексона: http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.8.2/jackson-databind-2.8.2.jar
Джексон-ломбок: http://repo1.maven.org/maven2/io/paradoxical/jackson-lombok/1.1/jackson-lombok-1.1.jar
Я компилирую его с помощью Netbeans (я не думаю, что это действительно актуально, но я все равно сообщаю об этом, чтобы сделать его идеально и точно воспроизводимым). Вышеупомянутые пять JAR хранятся в папке с именем " lib
" внутри папки проекта (вместе с " src
", " nbproject
", " test
" и " build
"). Я добавил их в Netbeans с помощью кнопки « Добавить JAR / папку » в свойствах проекта, и они перечислены в точном порядке, как в списке выше. Это стандартный проект типа «Java-приложение».
Кроме того, проект Netbeans настроен на « НЕ компилировать при сохранении », « генерировать отладочную информацию », « сообщать об устаревших API », « отслеживать зависимости java », « обрабатывать аннотации activacte » и « обрабатывать аннотации activacte в редакторе ». Обработчик аннотаций или опция обработки аннотаций явно не настроены в Netbeans. Кроме того, параметр -Xlint:all
командной строки "" передается в командной строке компилятора, и компилятор запускается на внешней виртуальной машине.
Моя версия javac - 1.8.0_72, а моя версия java - 1.8.0_72-b15. У меня Netbeans 8.1.
Мой проект компилируется нормально. Однако при его выполнении возникает исключение. Исключение не похоже на то, что кажется легко или очевидно исправимым. Вот результат, включая трассировку стека:
TestFoo(x=b, z=5)
{"z":5,"xoom":"a"}
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Argument #0 of constructor [constructor for testelombok.TestFoo, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[x, z]), interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
at [Source: {"z":5,"xoom":"a"}; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:296)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:269)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:475)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3890)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3785)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2833)
at testelombok.TestLombok.main(TestLombok.java:14)
Caused by: java.lang.IllegalArgumentException: Argument #0 of constructor [constructor for testelombok.TestFoo, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[x, z]), interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._addDeserializerConstructors(BasicDeserializerFactory.java:511)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:323)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:253)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:219)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:141)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:406)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:352)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
... 7 more
Я уже пытался о случайно тыкая с @Value
и @AllArgsConstructor
аннотации, но я не мог сделать это лучше.
Я погуглил исключение и нашел старый отчет об ошибке на Джексоне и еще один открытый, но, похоже, связанный с чем-то другим . Однако это все еще ничего не говорит о том, что это за ошибка или как ее исправить. Кроме того, я не мог найти ничего полезного в поисках чего-либо еще.
Поскольку то, что я пытаюсь сделать, - это очень простое использование ломбока и джексона, кажется странным, что я не смог найти более полезной информации о том, как решить эту проблему. Может я что то упустил?
Есть ли у кого-нибудь идеи, кроме как просто сказать « не используйте ломбок » или « не используйте Джексона », как это решить?
Неизменяемость + Ломбок + Джексон может быть достигнута следующим образом:
import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import lombok.Value; @Value @NoArgsConstructor(force = true, access = AccessLevel.PRIVATE) @AllArgsConstructor public class LocationDto { double longitude; double latitude; } class ImmutableWithLombok { public static void main(String[] args) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); String stringJsonRepresentation = objectMapper.writeValueAsString(new LocationDto(22.11, 33.33)); System.out.println(stringJsonRepresentation); LocationDto locationDto = objectMapper.readValue(stringJsonRepresentation, LocationDto.class); System.out.println(locationDto); } }
источник
AllArgsConstructor
часть@Value
аннотации?@NoArgsConstructor
переопределяет конструктор, созданный@Value
аннотацией, поэтому вам нужно добавить дополнительный@AllArgsConstructor
Я попробовал несколько из вышеперечисленных, и все они были темпераментными. Что действительно сработало для меня, так это ответ, который я нашел здесь .
в корневой каталог вашего проекта добавьте файл lombok.config (если вы еще этого не сделали)
и внутри вставьте это
lombok.anyConstructor.addConstructorProperties=true
Затем вы можете определить свои pojos следующим образом:
@Data @AllArgsConstructor public class MyPojo { @JsonProperty("Description") private String description; @JsonProperty("ErrorCode") private String errorCode; }
источник
У меня была точно такая же проблема, я "решил" ее, добавив
suppressConstructorProperties = true
параметр (на вашем примере):@Value @Wither @AllArgsConstructor(suppressConstructorProperties = true) public class TestFoo { @JsonProperty("xoom") private String x; private int z; }
Джексону явно не нравятся
java.beans.ConstructorProperties
аннотации, добавленные к конструкторам.suppressConstructorProperties = true
Параметр говорит Ломбок не добавить (это происходит по умолчанию).источник
suppressConstructorProperties
устарело :-(false
.@AllArgsConstructor(suppressConstructorProperties = true)
устарел. Определитьlombok.anyConstructor.suppressConstructorProperties=true
( https://projectlombok.org/features/configuration ) и изменить аннотацию ломбока POJO с@Value
на@Data
+@NoArgsConstructor
+@AllArgsConstructor
работает для меня.источник
Из ответа Яна Рике
Вам понадобится @JsonProperty в каждом поле, даже если имя совпадает, но в любом случае это хорошая практика. Вы также можете сделать свои поля общедоступными, используя это, что я предпочитаю геттерам.
@ToString @EqualsAndHashCode @Wither @AllArgsConstructor(onConstructor=@__(@JsonCreator)) public class TestFoo { @JsonProperty("xoom") public final String x; @JsonProperty("z") public final int z; }
Однако он также должен работать с геттерами (+ сеттерами).
источник
Can not deserialize instance of java.lang.String out of START_OBJECT token
... И это исправило! Мне нужно иметь эту@JsonProperty
аннотацию для каждого параметра конструктора, и это дополнение к@AllArgsConstructor
разрешению ломбока для этого инструмента.Для меня это сработало, когда я обновил версию lombok до: 'org.projectlombok: lombok: 1.18.0'
источник
Вы можете заставить Джексона поиграть с чем угодно, если воспользуетесь его паттерном "миксин" . По сути, это дает вам возможность добавлять аннотации Джексона к существующему классу без фактического изменения этого класса. Я склоняюсь к тому, чтобы рекомендовать его здесь, а не решение Lombok, потому что это решает проблему, которую Джексон имеет с функцией Джексона, поэтому с большей вероятностью он будет работать в долгосрочной перспективе.
источник
Все мои классы аннотированы следующим образом:
@JsonAutoDetect(fieldVisibility = Visibility.ANY) @JsonInclude(JsonInclude.Include.NON_DEFAULT) @Data @Accessors(fluent = true) @NoArgsConstructor @AllArgsConstructor
Он работал со всеми версиями Lombok и Jackson, по крайней мере, пару лет.
Пример:
@JsonAutoDetect(fieldVisibility = Visibility.ANY) @JsonInclude(JsonInclude.Include.NON_DEFAULT) @Data @Accessors(fluent = true) @NoArgsConstructor @AllArgsConstructor public class Person { String id; String first; String last; }
Вот и все. Ломбок и Джексон играют вместе как шарм.
источник
@JsonInclude(JsonInclude.Include.NON_NULL) @Data public class Person { String id; String first; String last; }
В дополнение к классу данных необходимо правильно настроить ObjectMapper. В этом случае он работает нормально с конфигурацией ParameterNamesModule и настройкой видимости полей и методов создателя.
om.registerModule(new ParameterNamesModule()); om.setVisibility(FIELD, JsonAutoDetect.Visibility.ANY); om.setVisibility(CREATOR, JsonAutoDetect.Visibility.ANY);
Тогда все должно работать как положено.
источник
У меня были проблемы с тем, чтобы Lombok не добавлял
ConstructorProperies
аннотацию, поэтому пошел другим путем и отключил Джексона от просмотра этой аннотации.Виной всему является JacksonAnnotationIntrospector.findCreatorAnnotation . Уведомление:
if (_cfgConstructorPropertiesImpliesCreator && config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
Также обратите внимание на JacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator :
public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b) { _cfgConstructorPropertiesImpliesCreator = b; return this; }
Таким образом , два варианта, либо установить
MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
ложь или создатьJacksonAnnotationIntrospector
наборsetConstructorPropertiesImpliesCreator
дляfalse
и установить этоAnnotationIntrospector
вObjectMapper
через ObjectMapper.setAnnotationIntrospector .Обратите внимание на пару моментов: я использую Jackson 2.8.10, а в этой версии
MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
его не существует. Я не уверен, в какой версии Джексона он был добавлен. Так что, если его нет, воспользуйтесьJacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator
механизмом.источник
Вам также понадобится этот модуль. https://github.com/FasterXML/jackson-modules-java8
затем включите флаг -параметры для вашего компилятора.
<build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin>
источник
Некоторое время я тоже боролся с этим. Но просматривая документацию здесь я вижу, что параметр аннотации onConstructor считается экспериментальным и плохо поддерживается в моей IDE (STS 4). Согласно документации Джексона, частные члены по умолчанию не (де) сериализуются. Есть быстрые способы решить эту проблему.
Добавьте аннотацию JsonAutoDetect и установите ее соответствующим образом для обнаружения защищенных / закрытых членов. Это удобно для DTO
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class SomeClass
Добавьте фабричную функцию с аннотацией @JsonCreator, это лучше всего работает, если вам нужна проверка объекта или дополнительные преобразования.
public class SomeClass { // some code here @JsonCreator public static SomeClass factory(/* params here dressing them in @JsonProperty annotations*/) { return new SomeClass(); } }
Конечно, вы также можете просто вручную добавить конструктор в себя.
источник
У меня была другая проблема, и это было с логическими примитивными типами.
private boolean isAggregate;
В результате возникла следующая ошибка
Exception: Unrecognized field "isAggregate" (class
Ламбок преобразуется
isAggregate
вisAggregate()
геттер,aggregate
вместо этого свойство внутренне превращается в ломбокisAggregate
. Библиотеке Джексона это не нравится, иisAggregate
вместо этого ей нужна собственность.Я обновил примитивное логическое значение до Wrapper Boolean, чтобы обойти эту проблему. Есть и другие варианты, если вы имеете дело с
boolean
типами, , см. Ссылку ниже.Sol:
private Boolean isAggregate;
ссылка: https://www.baeldung.com/lombok-getter-boolean
источник