JSON Jackson analysiert verschiedene Schlüssel in dasselbe Feld

Lesezeit: 4 Minuten

Benutzer-Avatar
DArkO

Ich habe ein POJO, das ein Feld hat:

public class Media {
 private Asset asset;
}

Alles funktioniert perfekt, wenn eine JSON-Antwort in dieses Asset-POJO geparst wird. Es gibt jedoch einen kleinen Unterschied zu dem Schlüssel, mit dem dieser Vermögenswert geliefert wird. Es kann entweder sein:

  @JsonProperty("cover_asset")

oder

  @JsonProperty("asset")

Gibt es eine Möglichkeit, das POJO zu kommentieren, um diesen Fall zu erkennen und in dasselbe Feld zu deserialisieren? Es ist nicht möglich, dass beide in derselben Antwort erscheinen.

  • Duplizieren: stackoverflow.com/questions/8560348/…

    – DRCB

    24. Oktober 2013 um 11:51 Uhr

Benutzer-Avatar
Vikas Prasad

Nun, da nur die Deserialisierung Ihr Anliegen ist, @JsonAlias eingeführt in 2.9 ist perfekt für diese Situation. Sie können so etwas tun:

@JsonAlias({"cover_asset", "asset"})
private Asset asset;

@JsonAlias Dokumente:

Anmerkung, die verwendet werden kann, um einen oder mehrere alternative Namen für eine Eigenschaft zu definieren, die während der Deserialisierung als Alternative zum offiziellen Namen akzeptiert werden. Alias-Informationen werden auch während der POJO-Introspektion offengelegt, haben jedoch keine Auswirkungen während der Serialisierung, bei der immer der primäre Name verwendet wird.

Hinweis: Stellen Sie sicher, dass Sie alle zugehörigen Abhängigkeiten aktualisieren (annotations, core, databind) wenn Sie sie verwenden. Nur aktualisieren annotations ohne andere warf mich Laufzeitfehler.

  • Habe nicht geprüft, ob der tatsächliche Feldname nach der Definition von Aliasen noch akzeptiert wird. Wenn ja, sogar @JsonAlias({"cover_asset"}) private Asset asset sollte arbeiten.

    – Vikas Prasad

    1. Dezember 2017 um 10:54 Uhr


  • Dies ist eine viel schönere und prägnantere Lösung, die jedoch nur in 2.9 verfügbar ist

    – comiventor

    11. Januar 2018 um 17:50 Uhr

  • Der Standardname wird unterstützt, sodass Sie in diesem Fall nur angeben müssen "cover_asset".

    – Coltin

    19. Juni 2018 um 17:50 Uhr

Kurz gesagt würde ich vorschlagen, dafür zwei separate @JsonSetter-Annotationen zu verwenden. Hier ist ein funktionierendes Beispiel. Das bedeutet, dass Ihre Java-Klasse statt zwei nur eine Getter-Methode für die Eigenschaft haben wird. Sie können auch den Setter, den Sie nicht für Clients von Media verfügbar machen möchten, privat machen und einen der JSON-Schlüssel auf besondere Weise behandeln.

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.ObjectMapper;

@SuppressWarnings("unused")
public class Media {

    private Asset asset;

    @JsonGetter("asset")
    public Asset getAsset() {
        return asset;
    }

    @JsonSetter("asset")
    public void setAsset(Asset asset) {
        this.asset = asset;
    }

    @JsonSetter("cover_asset")
    private void setMediaAsset(Asset asset) {
        if (this.asset == null) {
            setAsset(asset);
        }
    }


    private static class Asset {
        @JsonProperty("foo")
        private String foo;
    }

    public static void main(String[] args) throws Exception {
        String withAsset = "{'asset': {'foo':'bar'}}";
        String withCoverAsset = "{'cover_asset': {'foo':'bar'}}";

        ObjectMapper mapper = new ObjectMapper();
        Media mediaFromAsset = mapper.readValue(withAsset.replace('\'','"'), Media.class);
        Media mediaFromCoverAsset = mapper.readValue(withCoverAsset.replace('\'','"'), Media.class);

        System.out.println(mediaFromAsset.asset.foo.equals(mediaFromCoverAsset.asset.foo));

    }
}

  • Ich habe hier eine Frage: Warum ist die andere Setter-Methode (setMediaAsset()) privat?

    – naresh goty

    31. August 2016 um 17:13 Uhr

  • @nareshgoty, sodass die öffentliche API von Media einfach gehalten wird. Es gibt keinen guten Grund, zwei Setter-Methoden für dieselbe Eigenschaft verfügbar zu machen. Die private Methode existiert nur, damit Jackson sie aufrufen kann.

    – waley

    8. März 2017 um 15:33 Uhr

  • @nareshgoty Grundsätzlich sehen Sie in der Antwort json nur eine Eigenschaft, die Sie meiner Meinung nach erreichen möchten. In diesem Fall erhalten Sie “asset”:”

    – SinhaOjas

    20. Juli 2017 um 6:04 Uhr

Benutzer-Avatar
DRCB

Ich würde vorschlagen, Getter/Setter für beide Eigenschaftsnamen zu verwenden, die sich auf dasselbe POJO-Feld beziehen.

public class Media {
    private Asset asset;

    @JsonProperty("cover_asset")
    public Asset getCoverAsset() {
      return asset;
    }

    public void setCoverAsset(Asset asset) {
      this.asset= asset;
    }

    @JsonProperty("asset")
    public Asset getAsset() {
      return asset;
    }

    public void setAsset(Asset asset) {
      this.asset= asset;
    }
}

Siehe auch meine Antwort auf eine mögliche doppelte Frage: Unterschiedliche Namen der JSON-Eigenschaft während der Serialisierung und Deserialisierung

  • Ich habe das gesehen, aber ich versuche, dies vollständig zu vermeiden. Handhabung als 2 verschiedene Dinge, obwohl es sich tatsächlich nur um “Assets” handelt. Es stimmt jedoch, dass es mich dem, was ich erreichen möchte, einen Schritt näher bringt.

    – DArkO

    24. Oktober 2013 um 12:00 Uhr

Tolle Antwort von Vikas mit JsonAlias.

Fügen Sie nur hinzu, dass Sie auch von beiden Welten profitieren können (JsonProperty&Alias) [Since jackson 2.9]:

@JsonProperty("cover_asset")    
@JsonAlias({"asset", "cover_asset","amazing_asset"})
private Asset asset; 

Bezug.

1187400cookie-checkJSON Jackson analysiert verschiedene Schlüssel in dasselbe Feld

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

Privacy policy