90 votes

la classe A déclare plusieurs champs JSON

J'ai une classe A qui a des champs privés et la même classe étend une autre classe B qui a aussi des champs privés qui sont dans la classe A.

public class A extends B {
    private BigDecimal netAmountTcy;
    private BigDecimal netAmountPcy;   
    private BigDecimal priceTo;  
    private String segment;

    private BigDecimal taxAmountTcy;
    private BigDecimal taxAmountPcy;   
    private BigDecimal tradeFeesTcy;
    private BigDecimal tradeFeesPcy;

// getter and setter for the above fields

}

et la classe B a des fieds privés qui se trouvent dans la classe A

Lorsque j'essaie de créer une chaîne JSON à partir de la classe A ci-dessus, j'obtiens l'exception suivante :

class com.hexgen.ro.request.A declares multiple JSON fields named netAmountPcy

Comment résoudre ce problème ?

Comme il s'agit de champs privés, il ne devrait pas y avoir de problème lors de la création de la chaîne json, mais je n'en suis pas sûr.

Je crée une chaîne json comme suit :

Gson gson = new Gson();
 tempJSON = gson.toJson(obj);

obj est l'objet de la classe A

92voto

gerrytan Points 10345

Comme il s'agit de champs privés, il ne devrait pas y avoir de problème lors de la création de la chaîne json.

Je ne pense pas que cette affirmation soit vraie, GSON regarde les champs privés de l'objet lors de la sérialisation, ce qui signifie que tous les champs privés de la superclasse sont inclus, et lorsque vous avez des champs avec le même nom, il y a une erreur.

S'il y a un champ particulier que vous ne voulez pas inclure, vous devez le marquer avec la mention transient mot-clé, par exemple :

private transient BigDecimal tradeFeesPcy;

78voto

Adrian Lee Points 711

C'est un peu tard, mais j'ai rencontré exactement le même problème. La seule chose est que je n'ai pas pu modifier la superclasse car ce code n'était pas le mien. J'ai résolu le problème en créant une stratégie d'exclusion qui ignorait tout champ ayant un champ du même nom présent dans une superclasse. Voici mon code pour cette classe :

public class SuperclassExclusionStrategy implements ExclusionStrategy
{
    public boolean shouldSkipClass(Class<?> arg0)
    {
        return false;
    }

    public boolean shouldSkipField(FieldAttributes fieldAttributes)
    {
        String fieldName = fieldAttributes.getName();
        Class<?> theClass = fieldAttributes.getDeclaringClass();

        return isFieldInSuperclass(theClass, fieldName);            
    }

    private boolean isFieldInSuperclass(Class<?> subclass, String fieldName)
    {
        Class<?> superclass = subclass.getSuperclass();
        Field field;

        while(superclass != null)
        {   
            field = getField(superclass, fieldName);

            if(field != null)
                return true;

            superclass = superclass.getSuperclass();
        }

        return false;
    }

    private Field getField(Class<?> theClass, String fieldName)
    {
        try
        {
            return theClass.getDeclaredField(fieldName);
        }
        catch(Exception e)
        {
            return null;
        }
    }
}

J'ai ensuite défini les stratégies d'exclusion de la sérialisation et de la désérialisation dans le constructeur comme suit :

    builder.addDeserializationExclusionStrategy(new SuperclassExclusionStrategy());
    builder.addSerializationExclusionStrategy(new SuperclassExclusionStrategy());

J'espère que cela aidera quelqu'un !

20voto

Gangnus Points 7646

Le même message d'erreur se produit également si vous avez des champs différents, mais qu'ils ont la même valeur de @SerializedName .

@SerializedName("date_created")
private Date DateCreated;
@SerializedName("date_created")
private Integer matchTime;

En faisant du copier/coller, vous risquez de commettre une telle erreur. Regardez donc dans la classe et ses ancêtres et vérifier si c'est le cas.

  1. Vous ne pouvez pas avoir deux champs portant le même nom.
  2. Vous ne pouvez pas avoir deux champs avec le même nom sérialisé.
  3. Les types ne sont pas pertinents pour ces règles.

13voto

Saif Masadeh Points 280

J'ai utilisé GsonBuilder y ExclusionStrategy pour éviter les champs redondants comme ci-dessous, c'est simple et direct.

Gson json = new GsonBuilder()
          .setExclusionStrategies(new ExclusionStrategy() {
             @Override
             public boolean shouldSkipField(FieldAttributes f) {
                if(f.getName().equals("netAmountPcy")){
                   return true;
                }
                return false;
             }

             @Override
             public boolean shouldSkipClass(Class<?> clazz) {
                return false;
             }
          }).create();

6voto

Sujay Points 338

Ajouter les lignes suivantes au bas de proguard.config (si vous utilisez proguard dans le projet)

-keepclassmembers class * {
    private <fields>;    
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X