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

6voto

REM Code Points 53

En kotlin, l'ajout de l'élément @Transient pour la variable de la classe mère a fait l'affaire pour moi sur un projet de sealed avec des variables ouvertes.

4voto

Ogbe Points 718

Je ne pense pas qu'il faille rendre les membres transitoires, cela pourrait conduire à des erreurs car les membres dont vous pourriez avoir besoin à l'avenir pourraient être cachés.

La façon dont j'ai résolu ce problème est d'utiliser une stratégie de nommage personnalisée et d'ajouter le nom complet de la classe au Json. L'inconvénient de cette méthode est qu'elle conduit à un Json plus volumineux et si vous en avez besoin pour quelque chose comme une Api Rest, il serait bizarre pour les clients de nommer les champs de cette façon, mais je n'avais besoin de sérialiser que pour écrire sur le disque sur Android.

Voici donc la mise en œuvre d'une stratégie de dénomination personnalisée en Kotlin

import com.google.gson.FieldNamingStrategy
import java.lang.reflect.Field

  class GsonFieldNamingStrategy : FieldNamingStrategy {
     override fun translateName(field: Field?): String? {
        return "${field?.declaringClass?.canonicalName}.${field?.name}"
    }
}

Ainsi, pour tous les champs, le nom canonique complet serait ajouté, ce qui ferait que la classe enfant aurait un nom différent de la classe parent, mais lors de la désérialisation, la valeur de la classe enfant serait utilisée.

2voto

RominaV Points 1929

Dans mon cas, j'ai été assez bête 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);

2voto

Rafael Ruiz Muñoz Points 2260

Solution pour Kotlin, comme suggéré par @Adrian-Lee, vous devez modifier certaines vérifications de Null.

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
        }

    }
}

1voto

Besnik Points 3167

Pour les utilisateurs de Kotlin :

val fieldsToExclude = listOf("fieldToExclude", "otherFieldToExclude")

GsonBuilder()
    .setExclusionStrategies(object : ExclusionStrategy {
        override fun shouldSkipField(f: FieldAttributes?) = f?.let { fieldsToExclude.contains(it.name) } ?: false
        override fun shouldSkipClass(clazz: Class<*>?) = false
    })
    .create()

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