web-dev-qa-db-fra.com

JSON Jackson analyse différentes clés dans le même champ

J'ai un POJO qui a un champ:

public class Media {
 private Asset asset;
}

Tout fonctionne parfaitement lors de l'analyse d'une réponse json dans cet actif POJO. mais il existe cependant une légère différence avec la clé fournie avec cet actif. Il peut s'agir:

  @JsonProperty("cover_asset")

ou

  @JsonProperty("asset")

Existe-t-il un moyen d'annoter le POJO pour reconnaître ce cas et désérialiser dans le même champ. Il n'est pas possible que les deux apparaissent dans la même réponse.

46
DArkO

Plus succinctement, je suggère d'utiliser deux annotations @JsonSetter distinctes pour cela. Voici un exemple de travail. Cela signifie que votre classe Java aura seulement une méthode getter à utiliser pour la propriété au lieu de deux. Vous pouvez également rendre privé le setter que vous ne souhaitez pas exposer aux clients de Media et en traiter une des touches json d'une manière spéciale.

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));

    }
}
48
whaley

Eh bien, comme seule la désérialisation est votre préoccupation, @JsonAlias introduit dans 2.9 est parfait pour cette situation. Vous pouvez faire quelque chose comme ça:

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

@JsonAlias documents :

Annotation pouvant être utilisée pour définir un ou plusieurs noms alternatifs pour une propriété, acceptés lors de la désérialisation comme alternative au nom officiel. Les informations d'alias sont également exposées pendant l'introspection POJO, mais n'ont aucun effet pendant la sérialisation où le nom principal est toujours utilisé.

Remarque: assurez-vous de mettre à jour toutes les dépendances associées (annotations, core, databind) si vous les utilisez. La mise à jour juste annotations sans autre m'a jeté une erreur d'exécution.

59
Vikas Prasad