Verwendung der Annotation Jackson @JsonProperty für Kotlin-Datenklassen

Lesezeit: 5 Minuten

Benutzer-Avatar
Mike

kotlin 1.2.10 jackson-modul-kotlin:2.9.0

Ich habe die folgende Datenklasse in Kotlin:

data class CurrencyInfo(
        @JsonProperty("currency_info") var currencyInfo: CurrencyInfoItem?
)

@JsonInclude(JsonInclude.Include.NON_NULL)
data class CurrencyInfoItem(
        @JsonProperty("iso_4217") var iso4217: String?,
        @JsonProperty("name") var name: String?,
        @JsonProperty("name_major") var nameMajor: String?,
        @JsonProperty("name_minor") var nameMinor: String?,
        @JsonProperty("i_ma_currency") var iMaCurrency: Int?,
        @JsonProperty("i_merchant_account") var iMerchantAccount: Int?,
        @JsonProperty("i_x_rate_source") var iXRateSource: Int?,
        @JsonProperty("base_units") var baseUnits: Double?,
        @JsonProperty("min_allowed_payment") var minAllowedPayment: Int?,
        @JsonProperty("decimal_digits") var decimalDigits: Int?,
        @JsonProperty("is_used") var isUsed: Boolean?
)

Wenn ich versuche, diese Datenklasse zu deserialisieren, erhalte ich Folgendes:

{"currency_info":{"iso_4217":"CAD","name":"Canadian Dollar","imerchantAccount":0,"ixrateSource":2}}

Wie Sie sehen können, wurden die letzten beiden Optionen falsch deserialisiert. Dieses Problem könnte gelöst werden, indem Getter @get:JsonProperty direkt eine Anmerkung hinzugefügt wird. Laut Jackson Docs sollte @JsonProperty jedoch Gettern/Settern/Feldern zugewiesen werden

Ich möchte also fragen, ob es eine zuverlässige Möglichkeit gibt, die Eigenschaft für Jackson in Kotlin zu kommentieren, um eine korrekte Serialisierung/Deserialisierung zu haben (außerdem werden alle meine Datenklassen automatisch generiert, sodass es schwierig wäre, einige zwei- oder dreizeilige Anmerkungen separat für Getter zu erstellen und Setzer)

Könnte dieses Problem andernfalls durch einige Jackson-Einstellungen behoben werden?

Gemäß den Antworten unten funktioniert Folgendes für mich

private val mapper = ObjectMapper().registerKotlinModule()
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
.setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE)

  • Sie brauchen nur .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE). Das Problem hängt von der spezifischen Behandlung von “ist”-Gettern ab

    – Beloo

    15. Februar 2019 um 12:48 Uhr


Benutzer-Avatar
SimY4

@JsonProperty Anmerkungen in Ihrem Code werden alle in private Felder innerhalb Ihrer Datenklasse eingefügt, und standardmäßig scannt Jackson private Felder nicht nach Anmerkungen. Sie müssen es anweisen, etwas anderes zu tun, indem Sie setzen @JsonAutoDetect Anmerkung:

@JsonAutoDetect(fieldVisibility = Visibility.ANY)
data class CurrencyInfo(
    @JsonProperty("currency_info") var currencyInfo: CurrencyInfoItem?
)

Alternativ können Sie Ihre Anmerkungen zu Zugriffsmethoden verschieben:

data class CurrencyInfo(
    @get:JsonProperty("currency_info") var currencyInfo: CurrencyInfoItem?
)

  • Danke, ich habe den Sichtbarkeitsmodifikator global eingestellt

    – Mike

    27. Dezember 2017 um 15:25 Uhr

  • Ich habe jackson-annotations-2.9.0 und es gibt keine PRIVATE Möglichkeit. Ich habe es mit versucht ANYaber die Eigenschaft wird weiterhin ignoriert. Quellcode anzeigen

    – Mario Truco

    28. August 2018 um 8:49 Uhr


  • Die Antwort unten, die verwendet @param:JsonProperty("") ist auch kritisch, wenn Sie versuchen, dies für etwas zu replizieren, das nicht passiert, wenn Sie den Wert erhalten, dh benutzerdefinierte Json-Deserialisierer, die beim Bau auftreten.

    – Volleyball

    11. September 2019 um 21:23 Uhr


  • nichts davon funktioniert bei mir

    – Richa Schah

    17. November 2021 um 13:44 Uhr

  • Hallo, in Java ist es möglich, beim Serialisieren und Deserialisieren unterschiedliche jsonproperty-Namen zu haben. Ist es möglich, ähnliches für Felder in der Kotlin-Datenklasse zu tun? Aha @get:JsonProperty aber nicht @set:Jsonproperty. stackoverflow.com/questions/8560348/…

    – Erstpostkommentator

    9. Juli um 21:02 Uhr


Benutzer-Avatar
Maksim Turejew

Sie können so etwas tun:

data class CurrencyInfo @JsonCreator constructor (
        @param:JsonProperty("currency_info") 
        @get:JsonProperty("currency_info")
        val currencyInfo: CurrencyInfoItem?
)

Der obige Code wird in Java übersetzt als:

public final class CurrencyInfo {
   @Nullable
   private final String currencyInfo;

   @JsonProperty("currency_info")
   @Nullable
   public final String getCurrencyInfo() {
      return this.currencyInfo;
   }

   @JsonCreator
   public CurrencyInfo(@JsonProperty("currency_info") @Nullable String currencyInfo) {
      this.currencyInfo = currencyInfo;
   }
}

Der Code aus der akzeptierten Antwort wird wie folgt in Java übersetzt:

Erstens (ist nicht rein unveränderlich):

@JsonAutoDetect(
   fieldVisibility = Visibility.ANY
)
public final class CurrencyInfo {
   @Nullable
   private String currencyInfo;

   @Nullable
   public final String getCurrencyInfo() {
      return this.currencyInfo;
   }

   public final void setCurrencyInfo(@Nullable String var1) {
      this.currencyInfo = var1;
   }

   public CurrencyInfo(@JsonProperty("currency_info") @Nullable String currencyInfo) {
      this.currencyInfo = currencyInfo;
   }
}

Zweitens (hat wahrscheinlich Probleme mit der Deserialisierung):

public final class CurrencyInfo {
   @Nullable
   private final String currencyInfo;

   @JsonProperty("currency_info")
   @Nullable
   public final String getCurrencyInfo() {
      return this.currencyInfo;
   }

   public CurrencyInfo(@Nullable String currencyInfo) {
      this.currencyInfo = currencyInfo;
   }
}

Benutzer-Avatar
GameScripting

Sie können die hinzufügen jackson-module-kotlin (https://github.com/FasterXML/jackson-module-kotlin) und registrieren Sie das Kotlin-Modul bei Jackson:

val mapper = ObjectMapper().registerKotlinModule()

Dann funktioniert es (und vieles andere) automatisch.

  • Es wurde von Anfang an verwendet. Sie können sogar die Initialisierung im Frageposten überprüfen.

    – Mike

    12. Oktober 2018 um 12:39 Uhr

  • @ Mike ja, richtig, das habe ich verpasst. Es hat jedoch die Arbeit für mich erledigt.

    – GameScripting

    23. Oktober 2018 um 10:44 Uhr

  • Dies ist bei weitem die beste Antwort hier: Die Registrierung dieses Moduls löst nicht nur das Problem, ohne dass Sie tippen müssen @get: oder verwenden Sie andere Optimierungen, verbessert aber insgesamt die Kotlin<>Jackson-Interop.

    – verrückter Kopf

    19. September 2019 um 9:54 Uhr

  • KotlinModule() ist leider nicht in der letzten Version von Jackson enthalten, aber alle Dokumente sprechen leider über die Verwendung von KotlinModule(). niemand sagt, wie man das in der neuesten Version macht

    – metis

    13. April um 12:14 Uhr

  • @metis siehe github.com/FasterXML/jackson-module-kotlin#usage: ObjectMapper().registerKotlinModule()

    – GameScripting

    13. April um 14:41 Uhr

Sie können den ObjectMapper aus der Jackson-Bibliothek konfigurieren, indem Sie die Methode aufrufen setPropertyNamingStrategy(...)

Verwenden PropertyNamingStrategy.SNAKE_CASE sollte dein Problem lösen

Siehe auch die anderen verfügbaren Strategien hier: PropertyNamingStrategy

Kotlin unterstützt die Annotationen @param und @get nicht als eine Annotation, also müssen wir diesen Code schreiben:

data class User(
    @param:JsonProperty("id") @get:JsonProperty("id") val id: Int,
    @param:JsonProperty("name") @get:JsonProperty("name") val name: String
)

Hier können Sie JetBrain-Mitarbeitern mitteilen, diese Funktion zu unterstützen und Folgendes zuzulassen:

data class User(
    @JsonProperty("id") val id: Int,
    @JsonProperty("name") val name: String
)

https://youtrack.jetbrains.com/issue/KT-11005

Benutzer-Avatar
aSemy

Dieses Problem wurde in behoben

https://github.com/FasterXML/jackson-module-kotlin/issues/237

oder Sie können auch verwenden

data class SignRequest    
    @param:JsonProperty("estamp_request")
    @get:JsonProperty("estamp_request")
    val eStamp: EstampRequest?
}

data class EstampRequest(
    val tags: Map<String,Int>
)

Benutzer-Avatar
Ivan Rodrigues

Ich bin heute auf dieses Problem gestoßen und habe KotlinModule() in meinem ObjectMapper() registriert. Faltenbälge folgen einem Beispiel.

@Bean fun objectMapper = ObjectMapper().registreModule(KotlinModule())

Darüber befindet sich ein Dummy-ObjectMapper. Ich glaube, Sie sollten andere Konfigurationen in Ihren ObjectMapper einfügen, z. B. Serializer und so weiter

1055310cookie-checkVerwendung der Annotation Jackson @JsonProperty für Kotlin-Datenklassen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy