3
votes

Comment utiliser les noms de propriétés dynamiques pour un objet Json

Comment rendre le nom de propriété JSON dynamique. Par exemple

public class Value {
    @JsonProperty(value = "value")
    private String val;

    public void setVal(String val) {
        this.val = val;
    }

    public String getVal() {
        return val;
    }
}

lors de la sérialisation de cet objet, il est enregistré sous {"value": "actual_value_saved"} mais je veux rendre la clé aussi dynamique comme { "new_key": "actual_value_saved"} . Toute aide est très appréciée.


7 commentaires

Copie possible des noms de propriétés dynamiques Jackson


Voulez-vous l'enregistrer uniquement avec "new_key" ou voulez-vous l'enregistrer parfois avec "new_key" et parfois avec "value" ? et si oui pour quels motifs?


@Bentaye Oui, en fonction de l'exigence, le nom peut changer. il peut s'agir de "value" ou "new_key" ou "any_random_string"


@Prasad D'où provient le nom de champ requis? pouvez-vous le calculer à partir de votre objet Value?


@Bentaye J'ai parcouru les solutions en utilisant un JsonSerializer personnalisé ou JsonTypeInfo qui nous permet de modifier la valeur mais pas la clé. Mon exigence est d'avoir une clé dynamique. Je veux imprimer quelque chose comme ceci {"name": "user"} {"phone": "1234567890"} en utilisant ce POJO comme objet commun.


@Prasad oui j'ai supprimé mon commentaire, en essayant de le faire fonctionner


Les valeurs @Bentaye sont lues à partir d'un fichier CSV ou d'une base de données. En fait, le JSON sur lequel je travaille est énorme mais ce petit bout de code m'aidera à optimiser le nombre d'objets que je devrais utiliser dans mon application.


3 Réponses :


1
votes

Vous pouvez avoir tous les noms possibles comme variables, et les annoter afin qu'ils soient ignorés s'ils sont nuls. De cette façon, vous n'obtenez dans votre JSON que celui qui a une valeur

Puis changez votre setter pour qu'il alimente la variable mappée sur la clé que vous voulez.

class Value {

    @JsonProperty("val")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String val;

    @JsonProperty("new_key")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String newKey;

    @JsonProperty("any_random_string")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String anyRandomString;

    public void setVal(String s) {
        if(/* condition1 */)
            this.val = s;
        else if (/* condition2 */) {
            this.newKey = s;
        } else  if (/* condition3 */) {
            this.anyRandomString = s;
        }
    }

}


1 commentaires

Bonne idée cependant mais le nombre de champs à lire n'est pas le même à chaque fois. Ils ont tendance à changer en temps opportun, donc dans cette approche, je pourrais avoir besoin de mettre à jour le code à chaque fois qu'il y a un changement de champ.



2
votes

Vous pouvez utiliser JsonAnySetter JsonAnyGetter annotations. Derrière vous pouvez utiliser l'instance Map . Dans le cas où vous avez toujours one-key-object , vous pouvez utiliser Collections.singletonMap dans les autres cas, utilisez HashMap ou une autre implémentation. L'exemple ci-dessous montre à quel point vous pouvez utiliser cette approche et créer autant de clés aléatoires que vous le souhaitez:

{"name":"Vika"}
{"phone":"123-456-78-9"}
{"val":"VAL!"}

Le code ci-dessus imprime:

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        DynamicJsonsFactory factory = new DynamicJsonsFactory();
        ObjectMapper mapper = new ObjectMapper();

        System.out.println(mapper.writeValueAsString(factory.createUser("Vika")));
        System.out.println(mapper.writeValueAsString(factory.createPhone("123-456-78-9")));
        System.out.println(mapper.writeValueAsString(factory.any("val", "VAL!")));
    }
}

class Value {

    private Map<String, String> values;

    @JsonAnySetter
    public void put(String key, String value) {
        values = Collections.singletonMap(key, value);
    }

    @JsonAnyGetter
    public Map<String, String> getValues() {
        return values;
    }

    @Override
    public String toString() {
        return values.toString();
    }
}

class DynamicJsonsFactory {

    public Value createUser(String name) {
        return any("name", name);
    }

    public Value createPhone(String number) {
        return any("phone", number);
    }

    public Value any(String key, String value) {
        Value v = new Value();
        v.put(Objects.requireNonNull(key), Objects.requireNonNull(value));

        return v;
    }
}


0 commentaires

0
votes

Bonne question @Prasad, Cette réponse ne concerne pas JAVA ou SPRING BOOT, je mets juste cette réponse parce que j'ai cherché à faire cela avec node et j'espère que cela aidera quelqu'un d'une manière ou d'une autre. Dans JAVASCRIPT, nous pouvons ajouter des noms de propriétés dynamiques pour les objets JSON comme ci-dessous

var dogs = {};

var dogName = 'rocky';

dogs[dogName] = {
    age: 2,
    otherSomething: 'something'
};

dogName = 'lexy';

dogs[dogName] = {
    age: 3,
    otherSomething: 'something'
};

console.log(dogs);

Mais quand nous avons besoin de changer dynamiquement le nom, nous devons

  1. obtenir cette propriété
  2. et créez une autre propriété avec le même contenu et un nouveau nom
  3. et supprimez l'ancienne propriété de JSON
  4. attribuer la nouvelle propriété au JSON

existe-t-il un autre moyen de changer dynamiquement le nom JSON à l'exception de cette méthode, merci d'avance


0 commentaires