ジャクソン(カスタムデシリアライザなし)単一値の値オブジェクトをデシリアライズするための一般的な方法はあります

マルク・フォン・Renteln:

私たちは、単一の値で値オブジェクトの多くを使用します。(縮小)直列化のために我々はkotlinモジュールでジャクソンを使用しています。

Kotlinの例値オブジェクト:

data class MyValueObject(val value: String)

やJavaなど

class MyValueObject {
 private String value;

 public MyValueObject(String value) { this.value = value; }

 public String getValue() { return value; }
}

これらの値オブジェクトをシリアル化する必要がありおよび非直列化など、および「値のみ」をシリアル化する必要があります。"theValue"代わりに"{"value":"theValue"}"

私は、値オブジェクトの数十のためのカスタムシリアライザ/デシリアライザを書き込まないようしたいと思います。

私は、シリアル化のために知って@JsonValueこれを実現するために使用することができます。

data class MyValueObject(@JsonValue val value: String)

しかし、JSON「」theValueは、「」(シリアル化された文字列リテラル以上)として戻って非直列化することはできませんMyValueObjectこれは、次の例外にsesults:

com.fasterxml.jackson.databind.exc.MismatchedInputException: 
Cannot construct instance of `[...].MyValueObject` (although at least one Creator exists): 
no String-argument constructor/factory method to deserialize from String value ('test')
 at [Source: (String)""test""; line: 1, column: 1]

ここではユニットテスト私が使用されます。

@Test
fun testSerialize() {
    val objectMapper = ObjectMapper()
        .registerModule(Jdk8Module())
        .registerModule(KotlinModule())
    val test = MyValueObject("test")
    val json = objectMapper.writeValueAsString(test)
    println(json)
    objectMapper.readValue<MyValueObject>(json)
}

以下のように、これらをデシリアライズするための簡単な/汎用的な方法がある@JsonValueシリアル化のためには?

PS:一つの作業溶液(@LppEddのおかげで)次のとおりです。

data class MyValueObject (@JsonValue val value: String) {

    companion object {
        @JvmStatic
        @JsonCreator
        fun create(value: String) = MyValueObject(value)
    }
}

しかし、これは非常に冗長です。コンストラクタに注釈を付け@JsonCreatorは私のために仕事をしませんでした(@LppEddの答えに私のコメントを参照してください)

LppEdd:

確かに、それは非常に簡単です。
ただ、追加@JsonCreatorコンストラクタに。

class MyValueObject {
  private String value;

  @JsonCreator
  public MyValueObject(String value) { this.value = value; }

  @JsonValue
  public String getValue() { return value; }
}

それともあなたは持っているだろうKotlinのために、私は考え

data class MyValueObject @JsonCreator constructor(@JsonValue val value: String)

あなたは、使用する場合@JsonCreator なしでコンストラクタパラメータを接頭辞

@JsonProperty("fieldName")

あなたは、あなたのケースでは、単に「原始」の値で全体のJSON文字列を、渡すためにジャクソンを教えてください。


どうやらKotlinは、自動生成されたゲッター/セッターのペアが好きではありません。
これは、例えば作品

class MyValueObject @JsonCreator constructor(private val value: String) {
    @JsonValue
    fun getValue() = value
}

また、デバッグのビットの後、私はこの問題は、ここで発生してい

@Override
public Boolean hasAsValue(Annotated a) {
    JsonValue ann = _findAnnotation(a, JsonValue.class);
    if (ann == null) {
        return null;
    }
    return ann.value();
}

JacksonAnnotationIntrospector

私はなぜ知らないが、ジャクソンはまだ探し@JsonValueの注釈のパブリックフィールドまたは上のパブリックゲッター。Kotlinは上の注釈を置くプライベートフィールドなので、ジャクソンはそれを見つけることができません。

解決策は、

data class MyValueObject @JsonCreator constructor(@JvmField @JsonValue val value: String)

またはより良いです

data class MyValueObject @JsonCreator constructor(@get:JsonValue val value: String)

マルク・フォン・Rentelnはコメントで書いたように、あなたも省略することができます @JsonCreator

data class MyValueObject(@get:JsonValue val value: String)

これはしかし、文書化されていないようです。この動作が記載されている場合、誰かが指摘することができた場合、それは素晴らしいだろう!

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=185021&siteId=1