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 fiedls privés qui sont en classe A

Maintenant, quand 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 ce sont des champs privés, il ne devrait pas y avoir de problème lors de la création d'une chaîne json, je suppose, mais je ne le suis pas assurer.

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

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

Ici obj est l'objet de la classe A

50
demandé sur gerrytan 2013-05-10 10:35:57

6 réponses

comme ce sont des champs privés, il ne devrait y avoir aucun problème lors de la création de la chaîne json

Je ne pense pas que cette déclaration 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 superclasse sont inclus, et lorsque vous avez des champs avec le même nom, il génère une erreur.

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

private transient BigDecimal tradeFeesPcy;
59
répondu gerrytan 2013-05-10 07:00:51

C'est un peu tard, mais j'ai rencontré exactement le même problème. La seule chose était que je n'étais pas capable de modifier la superclasse car ce code n'était pas le mien. La façon dont j'ai résolu cela était 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 sérialisation et de désérialisation dans le générateur comme suit:

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

Espérons que cela aide à quelqu'un!

53
répondu Adrian Lee 2013-11-21 10:06:58

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

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

Faire copier / coller Vous pouvez simplement faire une telle erreur. Alors, regardez dans la classe et ses ancêtres et vérifiez cela.

9
répondu Gangnus 2018-01-23 12:26:26

Ajoutez les lignes suivantes au bas de proguard.config (si vous utilisez proguard en projet)

-keepclassmembers class * {
    private <fields>;    
}
2
répondu Sujay 2017-12-22 07:22:32

Solution pour Kotlin, comme suggéré @Adrian-Lee, vous devez modifier certaines vérifications nulles

class SuperclassExclusionStrategy : ExclusionStrategy {

    override fun shouldSkipClass(clazz: Class<*>?): Boolean {
        return false
    }

    override fun shouldSkipField(f: FieldAttributes?): Boolean {
        val fieldName = f?.name
        val theClass = f?.declaringClass

        return isFieldInSuperclass(theClass, fieldName)
    }

    private fun isFieldInSuperclass(subclass: Class<*>?, fieldName: String?): Boolean {
        var superclass: Class<*>? = subclass?.superclass
        var field: Field?

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

            if (field != null)
                return true

            superclass = superclass.superclass
        }

        return false
    }

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

    }
}
1
répondu Rafael Ruiz Muñoz 2018-03-26 21:26:32

Dans mon cas, j'étais assez stupide pour enregistrer un adaptateur avec la classe X, et essayer de sérialiser fromJson avec la classe Y:

        final GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapter(Game.class, new TournamentSerializer());
        final Gson gson = gsonBuilder.create();

        createdTournament = gson.fromJson(jsonResponse.toString(), Tournament.class);
0
répondu RominaV 2016-04-28 18:31:59