Klasse A deklariert mehrere JSON-Felder

Lesezeit: 6 Minuten

Benutzer-Avatar
Java-Fragen

Ich habe eine Klasse A, die einige private Felder hat, und dieselbe Klasse erweitert eine andere Klasse B, die auch einige private Felder hat, die in Klasse A sind.

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

}

und Klasse B hat einige private Felder, die in Klasse A sind

Wenn ich jetzt versuche, eine JSON-Zeichenfolge aus der obigen Klasse A zu erstellen, erhalte ich die folgende Ausnahme:

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

Wie kann man das beheben?

Da es sich um private Felder handelt, sollte es beim Erstellen von JSON-Strings kein Problem geben, denke ich, aber ich bin mir nicht sicher.

Ich erstelle JSON-String wie folgt:

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

hier ist obj das Objekt der Klasse A

  • Poste deine Superklasse B.

    – NPKR

    10. Mai 2013 um 7:08 Uhr

Da es sich um private Felder handelt, sollte es beim Erstellen von JSON-Strings keine Probleme geben

Ich glaube nicht, dass diese Aussage wahr ist, GSON schlägt beim Serialisieren die privaten Felder des Objekts nach, was bedeutet, dass alle privaten Felder der Oberklasse enthalten sind, und wenn Sie Felder mit demselben Namen haben, wird ein Fehler ausgegeben.

Wenn Sie ein bestimmtes Feld nicht einschließen möchten, müssen Sie es mit markieren transient Stichwort, zB:

private transient BigDecimal tradeFeesPcy;

  • Danke es funktioniert. Aber warum funktioniert die @Expose-Annotation von Gson nicht mit dem Feld der Oberklasse und sorgt für Verwirrung?

    – Facher

    19. Mai 2017 um 15:19 Uhr

  • @Fakher zu bekommen @Expose richtig funktioniert, müssen Sie einstellen @Expose(serialize = false)und unbedingt anrufen excludeFieldsWithoutExposeAnnotation()auf Ihrem GsonBuilder Objekt.

    – Ibrahim.H

    12. Februar 2018 um 10:49 Uhr


  • Dieser Kommentar hat mein Problem perfekt gelöst. Verwenden new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(YOUR_OBJECT)Es klappt

    – Zweck PI

    22. Juli 2019 um 4:55 Uhr


  • Wenn Sie mit Kotlin arbeiten, gibt es dafür eine Anmerkung: kotlin /** * Marks the JVM backing field of the annotated property as `transient`, meaning that it is not * part of the default serialized form of the object. */ @Target(FIELD) @Retention(AnnotationRetention.SOURCE) @MustBeDocumented public actual annotation class Transient

    – AouledIssa

    10. Oktober 2020 um 20:48 Uhr


Das ist ein bisschen spät, aber ich bin auch auf genau das gleiche Problem gestoßen. Das einzige war, dass ich die Oberklasse nicht ändern konnte, da dieser Code nicht von mir stammte. Ich habe dies gelöst, indem ich eine Ausschlussstrategie erstellt habe, die jedes Feld übersprungen hat, das ein Feld mit demselben Namen in einer Oberklasse hatte. Hier ist mein Code für diese Klasse:

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

Ich habe dann die Ausschlussstrategien für Serialisierung und Deserialisierung im Builder wie folgt festgelegt:

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

Hoffentlich hilft das jemandem!

  • Dies ist die richtige Antwort, da ich das Objekt der Superklasse nicht von der Serialisierung ausschließen möchte, ich möchte nur nicht, dass GSON die Variable der erweiterten Klasse ausschließt

    – CQM

    28. Februar 2014 um 17:07 Uhr

  • Meiner Meinung nach ist das der falsche Weg. Auf diese Weise enthält Ihr JSON die Variable aus der Superklasse und der Wert der Unterklasse wird ausgeblendet. Man würde es umgekehrt erwarten; die Unterklassenvariable in json haben und die Oberklassenvariable ausblenden.

    – Veden

    9. Dezember 2015 um 12:57 Uhr

  • @Veda, hast du eine umgekehrte Lösung gefunden? Ich stehe vor der gleichen Situation, in der ich untergeordnete Variablen und Werte benötige.

    – Lernender

    22. März 2018 um 17:03 Uhr

  • Ich denke, um das Gegenteil zu tun, müssen Sie wissen, ob der Typ, den Sie betrachten, der Untertyp eines anderen Typs ist. Es scheint viel schwieriger zu sein (wenn es überhaupt möglich ist), den Vererbungsbaum von der anderen Seite nach oben zu schauen. stackoverflow.com/questions/492184/…

    – jokul

    6. August 2018 um 20:09 Uhr

  • Die akzeptierte Antwort funktioniert besser. Wenn die oberste Klasse das Feld als transient markiert, obwohl es den gleichen Namen wie die untere Klasse hat, wird es von der Serialisierung ausgeschlossen.

    – CompEng88

    20. September 2019 um 21:12 Uhr

Benutzer-Avatar
Gangnus

Dieselbe Fehlermeldung tritt auch auf, wenn Sie unterschiedliche Felder haben, diese aber gleich sind @SerializedName.

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

Beim Kopieren / Einfügen können Sie einfach einen solchen Fehler machen. Schauen Sie also in die Klasse und seine Vorfahren und prüfe das.

  1. Sie können nicht zwei Felder mit demselben Namen haben.
  2. Sie können nicht zwei Felder mit demselben serialisierten Namen haben.
  3. Typen sind für diese Regeln irrelevant.

  • Was ist, wenn meine JSON-Datei tatsächlich denselben Namen mit unterschiedlichen Typen hat (absichtlich)? dh einige Endpunkte “main_id” ist ein Int, einige andere Endpunkte “main_id” ist ein String

    – Ben Akin

    1. Juni 2020 um 5:28 Uhr

  • 1. Sie können nicht zwei Felder mit demselben Namen haben. 2. Sie können nicht zwei Felder mit demselben serialisierten Namen haben. 3. Typen sind in diesen Regeln irrelevant.

    – Gangnus

    1. Juni 2020 um 8:48 Uhr

  • Bei mir funktioniert nur diese Lösung.

    – Ahamadullah Saikat

    19. Mai um 9:42 Uhr

Benutzer-Avatar
Saif

ich benutzte GsonBuilder und ExclusionStrategy Um die redundanten Felder wie unten zu vermeiden, ist es einfach und unkompliziert.

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

Fügen Sie die folgenden Zeilen am Ende von proguard.config hinzu
(wenn Sie proguard im Projekt verwenden)

-keepclassmembers class * {
    private <fields>;    
}

Benutzer-Avatar
Rakesch

In meinem Fall war ich dumm genug, einen Adapter mit der X-Klasse zu registrieren und zu versuchen, fromJson mit der Y-Klasse zu serialisieren:

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

createdTournament = gson.fromJson(jsonResponse.toString(), Tournament.class);

Benutzer-Avatar
REM-Code

In kotlin Hinzufügen der @Transient Die Anmerkung für die Variable in der übergeordneten Klasse hat bei a den Trick für mich getan sealed Klasse mit offenen Variablen.

  • das funktioniert in Kotlin für mich. Danke

    – Bob Redity

    27. Mai um 11:57 Uhr

  • Andere Antworten haben mehr Upvotes, aber diese Antwort bekommt meine. Ich hatte offene Werte für eine abstrakte Basisklasse, die ich in einer Unterklasse überschrieb. Das verwirrte Gson. @Transient in den offenen Eigenschaften der Basisklasse behebt dies.

    – Weißt du

    20. Juli um 21:00 Uhr


1245640cookie-checkKlasse A deklariert mehrere JSON-Felder

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy