ジャクソンとロンボクを組み合わせて実験しています。これらは私のクラスです:
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);
}
}
これらは、classpthに追加するJARです。
ロンボク: https://projectlombok.org/downloads/lombok.jar (バージョン1.16.10)
ジャクソンのコア: 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でコンパイルしています(これは本当に関連があるとは思いませんが、とにかくこれを報告して、完全かつ忠実に再現できるようにします)。上記の5つのJARは、プロジェクトフォルダー内の「lib
」というフォルダーに保存されます(「src
」、「nbproject
」、「test
」、「build
」とともに)。プロジェクトのプロパティの「Add JAR/Folder」ボタンを使用してそれらをNetbeansに追加しましたが、上記のリストと同じ順序でリストされています。プロジェクトは、標準の「Javaアプリケーション」タイプのプロジェクトです。
さらに、Netbeansプロジェクトは、「保存時にコンパイルしない」、「デバッグ情報を生成する」、「レポート非推奨API」、「 track Java依存関係 "、" activacteアノテーションの処理 "および" エディターでのアノテーションの処理の処理 "。 Netbeansでは、注釈プロセッサまたは注釈処理オプションは明示的に構成されていません。また、「-Xlint:all
」コマンドラインオプションはコンパイラコマンドラインで渡され、コンパイラは外部VMで実行されます。
私の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
アノテーションをランダムに突っ込んでみましたが、これ以上改善することはできませんでした。
私は例外をグーグルでやりました jacksonの古いバグレポートを見つけました 、および 開いているが、何か他のものに関連しているように見える 。ただし、これでもこのバグの内容や修正方法については何もわかりません。また、私はそれをどこか他の場所で見るのに役立つものを見つけることができませんでした。
私がやろうとしているのはロンボクとジャクソンの両方の非常に基本的な使用方法であるため、この問題を回避する方法に関する有用な情報を見つけることができなかったようです。たぶん私は何かを見逃しましたか?
「lombokを使用しない」または「jacksonを使用しない」と言う以外に、これを解決する方法について誰もが考えていますか?
不変であるが、lombokとjacksonを使用したjsonシリアライズ可能なPOJOが必要な場合。 lomboksビルダーでjacksonsの新しいアノテーションを使用する@JsonPOJOBuilder(withPrefix = "")
このソリューションを試しましたが、非常にうまく機能します。サンプル使用法
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.Builder;
import lombok.Value;
@JsonDeserialize(builder = Detail.DetailBuilder.class)
@Value
@Builder
public class Detail {
private String url;
private String userName;
private String password;
private String scope;
@JsonPOJOBuilder(withPrefix = "")
public static class DetailBuilder {
}
}
@Builder
を持つクラスが多すぎて、ボイラープレートコードの空の注釈を望まない場合は、注釈インターセプターをオーバーライドして空のwithPrefix
にすることができます。
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) {
if (ac.hasAnnotation(JsonPOJOBuilder.class)) {//If no annotation present use default as empty prefix
return super.findPOJOBuilderConfig(ac);
}
return new JsonPOJOBuilder.Value("build", "");
}
});
また、@JsonPOJOBuilder
アノテーションを使用して空のビルダークラスを削除できます。
私はまったく同じ問題を抱えていました。suppressConstructorProperties = true
パラメーターを追加して「解決」しました(例を使用)。
@Value
@Wither
@AllArgsConstructor(suppressConstructorProperties = true)
public class TestFoo {
@JsonProperty("xoom")
private String x;
private int z;
}
ジャクソンは、コンストラクタに追加された Java.beans.ConstructorProperties
注釈が嫌いなようです。 suppressConstructorProperties = true
パラメーターは、 Lombok を追加しないように指示します(デフォルトで追加します)。
不変+ロンボク+ジャクソンは、次の方法で実現できます。
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(suppressConstructorProperties = true)
は非推奨です。 lombok.anyConstructor.suppressConstructorProperties=true
( https://projectlombok.org/features/configuration )を定義し、POJOのlombokアノテーションを@Value
から@Data
+ @NoArgsConstructor
+に変更します@AllArgsConstructor
は私のために働きます。
上記のいくつかを試しましたが、それらはすべて気まぐれでした。私にとって本当に役立ったのは、私が見つけた答えです ここ 。
プロジェクトのルートディレクトリにファイルを追加します(まだ行っていない場合)
lombok.config
内側に貼り付けます
lombok.anyConstructor.addConstructorProperties=true
次に、次のようにpojoを定義できます。
@Data
@AllArgsConstructor
public class MyPojo {
@JsonProperty("Description")
private String description;
@JsonProperty("ErrorCode")
private String errorCode;
}
私にとっては、ロンボクのバージョンを「org.projectlombok:lombok:1.18.0」に更新したときに機能しました
このモジュールも必要です。 https://github.com/FasterXML/jackson-modules-Java8
次に、コンパイラの-parametersフラグをオンにします。
<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>
"mixin" pattern を使用すれば、ジャクソンにほぼ何でも遊ばせることができます。基本的に、既存のクラスを実際に変更することなく、そのクラスにジャクソン注釈を追加する方法を提供します。ジャクソンがジャクソンの機能で抱えている問題を解決するため、ロンボクのソリューションではなくここでそれを推奨することに傾いています。
Lombok 1.18.4以降、コンストラクターパラメーターにコピーされる注釈を構成できます。これを
lombok.config
に挿入します:lombok.copyableAnnotations += com.fasterxml.jackson.annotation.JsonProperty
次に、
@JsonProperty
をフィールドに追加します。...
名前が一致する場合でも、すべてのフィールドに@JsonPropertyが必要になりますが、とにかく従うことをお勧めします。また、これを使用してフィールドをパブリックファイナルに設定することもできます。
@ToString
@EqualsAndHashCode
@Wither
@AllArgsConstructor(onConstructor=@__(@JsonCreator))
public class TestFoo {
@JsonProperty("xoom")
private final String x;
@JsonProperty("z")
private final int z;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public class Person {
String id;
String first;
String last;
}
データクラスに加えて、ObjectMapperを正しく構成する必要があります。この場合、ParameterNamesModule構成で正常に動作し、FieldsおよびCreatorメソッドの可視性を設定しています
om.registerModule(new ParameterNamesModule());
om.setVisibility(FIELD, JsonAutoDetect.Visibility.ANY);
om.setVisibility(CREATOR, JsonAutoDetect.Visibility.ANY);
その後、期待どおりに動作するはずです。
私もこれに少し苦労しました。しかし、ドキュメントを見ると here onConstructorアノテーションパラメータは実験的であると見なされ、IDE(STS 4)では十分にサポートされていないことがわかります。 Jacksonのドキュメントによると、プライベートメンバーはデフォルトでは(デ)シリアル化されていません。これを解決する簡単な方法があります。
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();
}
}
もちろん、コンストラクタを自分で手動で追加することもできます。
私はすべてのクラスにこのように注釈を付けました:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@Data
@Accessors(fluent = true)
@NoArgsConstructor
@AllArgsConstructor
少なくとも数年間、すべてのロンボクとジャクソンのバージョンで動作しました。
例:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@Data
@Accessors(fluent = true)
@NoArgsConstructor
@AllArgsConstructor
public class Person {
String id;
String first;
String last;
}
以上です。ロンボクとジャクソンは魅力のように一緒に遊ぶ。
LombokにConstructorProperies
注釈を追加しないようにすることで問題が発生していたため、反対に進み、Jacksonがその注釈を表示できないようにしました。
原因は JacksonAnnotationIntrospector.findCreatorAnnotation です。通知:
if (_cfgConstructorPropertiesImpliesCreator
&& config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
また注意してください JacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator :
public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b)
{
_cfgConstructorPropertiesImpliesCreator = b;
return this;
}
したがって、2つのオプションは、MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
をfalseに設定するか、JacksonAnnotationIntrospector
を作成してsetConstructorPropertiesImpliesCreator
をfalse
に設定し、このAnnotationIntrospector
をObjectMapper
に設定します ObjectMapper.setAnnotationIntrospector 。
いくつかのことに注意してください。私はJackson 2.8.10を使用しており、そのバージョンにはMapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
は存在しません。ジャクソンのどのバージョンに追加されたのかわかりません。したがって、存在しない場合は、JacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator
メカニズムを使用します。
@NoArgsConstructorを追加してみてください