Gson: So schließen Sie bestimmte Felder ohne Anmerkungen von der Serialisierung aus

Lesezeit: 11 Minuten

Gson So schliesen Sie bestimmte Felder ohne Anmerkungen von der
Liviu T.

Ich versuche Gson zu lernen und kämpfe mit Feldausschluss. Hier sind meine Klassen

public class Student {    
  private Long                id;
  private String              firstName        = "Philip";
  private String              middleName       = "J.";
  private String              initials         = "P.F";
  private String              lastName         = "Fry";
  private Country             country;
  private Country             countryOfBirth;
}

public class Country {    
  private Long                id;
  private String              name;
  private Object              other;
}

Ich kann den GsonBuilder verwenden und eine ExclusionStrategy für einen Feldnamen wie hinzufügen firstName oder country aber ich kann es anscheinend nicht schaffen, Eigenschaften bestimmter Felder wie auszuschließen country.name.

Mit der Methode public boolean shouldSkipField(FieldAttributes fa)FieldAttributes enthält nicht genügend Informationen, um das Feld mit einem Filter wie abzugleichen country.name.

PS: Ich möchte Anmerkungen vermeiden, da ich dies verbessern und RegEx verwenden möchte, um Felder herauszufiltern.

Bearbeiten: Ich versuche zu sehen, ob es möglich ist, das Verhalten von zu emulieren Struts2-JSON-Plugin

mit Gson

<interceptor-ref name="json">
  <param name="enableSMD">true</param>
  <param name="excludeProperties">
    login.password,
    studentList.*\.sin
  </param>
</interceptor-ref>

Bearbeiten:
Ich habe die Frage mit folgendem Zusatz erneut geöffnet:

Ich habe ein zweites Feld mit demselben Typ hinzugefügt, um dieses Problem weiter zu verdeutlichen. Grundsätzlich möchte ich ausschließen country.name aber nicht countrOfBirth.name. Ich möchte Land auch nicht als Typ ausschließen. Die Typen sind also dieselben, es ist die tatsächliche Stelle im Objektdiagramm, die ich lokalisieren und ausschließen möchte.

  • Ab Version 2.2 kann ich immer noch keinen Pfad zum auszuschließenden Feld angeben. flexjson.sourceforge.net fühlt sich nach einer guten Alternative an.

    – Liviu T.

    8. Februar 2013 um 21:50 Uhr

  • Schauen Sie sich meine Antwort auf eine ziemlich ähnliche Frage an. Es basiert auf der Erstellung einer benutzerdefinierten JsonSerializer für irgendeinen Typ –Country in Ihrem Fall – wofür dann eine angewendet wird ExclusionStrategy die entscheidet, welche Felder serialisiert werden.

    – Pirho

    24. Dezember 2017 um 0:02 Uhr

  • stackoverflow.com/questions/3544919/…

    – Pangamma

    29. Januar 2019 um 5:34 Uhr

Gson So schliesen Sie bestimmte Felder ohne Anmerkungen von der
Chris Seline

Alle Felder, die Sie im Allgemeinen nicht serialisieren möchten, sollten Sie den Modifikator “transient” verwenden, und dies gilt auch für json-Serialisierer (zumindest für einige, die ich verwendet habe, einschließlich gson).

Wenn Sie nicht möchten, dass der Name im serialisierten JSON angezeigt wird, geben Sie ihm ein vorübergehendes Schlüsselwort, z.

private transient String name;

Weitere Details in der Gson-Dokumentation

  • Es ist fast dasselbe wie eine Ausschlussanmerkung, da es für alle Instanzen dieser Klasse gilt. Ich wollte einen dynamischen Ausschluss zur Laufzeit. In einigen Fällen möchte ich, dass einige Felder ausgeschlossen werden, um eine leichtere/eingeschränkte Antwort bereitzustellen, und in anderen möchte ich, dass das vollständige Objekt serialisiert wird

    – Liviu T.

    7. Mai 2011 um 7:36 Uhr

  • Zu beachten ist, dass Transient sowohl die Serialisierung als auch die Deserialisierung beeinflusst. Es gibt auch den Wert aus, der in das Objekt serialisiert wurde, selbst wenn er in JSON vorhanden ist.

    – Kong

    16. April 2013 um 3:48 Uhr

  • Das Problem mit der Nutzung transient anstatt @Expose ist, dass Sie immer noch ein POJO auf Ihrem Client mit allen Feldern erstellen müssen, die möglicherweise eingehen könnten. Im Fall einer Back-End-API, die möglicherweise von Projekten gemeinsam genutzt wird, könnte dies problematisch sein, falls zusätzliche Felder hinzugefügt werden. Im Wesentlichen handelt es sich um Whitelisting vs. Blacklisting der Felder.

    – das Blang

    25. November 2014 um 17:08 Uhr

  • Dieser Ansatz hat bei mir nicht funktioniert, da er nicht nur das Feld von der gson-Serialisierung ausschloss, sondern auch das Feld von der internen App-Serialisierung (unter Verwendung der Serializable-Schnittstelle).

    – Pck

    16. Januar 2015 um 14:52 Uhr

  • transient verhindert die SERIALISIERUNG und DESERIALISIERUNG eines Felds. Das entspricht nicht meinen Anforderungen.

    – Lönix

    20. Juli 2015 um 8:18 Uhr

Gson So schliesen Sie bestimmte Felder ohne Anmerkungen von der
JayPea

Nishant hat eine gute Lösung bereitgestellt, aber es gibt einen einfacheren Weg. Markieren Sie einfach die gewünschten Felder mit der @Expose-Anmerkung, wie zum Beispiel:

@Expose private Long id;

Lassen Sie alle Felder aus, die Sie nicht serialisieren möchten. Dann erstellen Sie einfach Ihr Gson-Objekt auf diese Weise:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

  • Ist es möglich, so etwas wie “notExpose” zu haben und diese nur zu ignorieren, wenn alle bis auf ein Feld serialisiert werden müssen und das Hinzufügen von Anmerkungen zu allen überflüssig ist?

    – Daniil Shevelev

    18. Februar 2014 um 0:19 Uhr

  • @DaSh Ich hatte kürzlich ein solches Szenario. Es war sehr einfach, eine benutzerdefinierte ExclusionStrategy zu schreiben, die genau das tat. Siehe Nishants Antwort. Das einzige Problem bestand darin, eine Reihe von Containerklassen einzuschließen und mit skipclass vs skipfield herumzuspielen (Felder können Klassen sein …)

    – Schlüssel

    14. Juli 2014 um 11:20 Uhr


  • @DaSh Meine Antwort unten macht genau das.

    – Derek Shockey

    26. August 2014 um 3:37 Uhr

  • Was für eine tolle Lösung. Ich bin auf ein Szenario gestoßen, in dem ich möchte, dass ein Feld auf der Festplatte serialisiert wird, aber ignoriert wird, wenn es über gson an einen Server gesendet wird. Perfekt danke!

    – Schlau

    16. September 2015 um 15:15 Uhr

  • @Danlil Sie sollten in der Lage sein, @Expose (serialisieren = falsch, deserialisieren = falsch) zu verwenden.

    – HRK

    13. Juni 2016 um 12:28 Uhr

1646258232 858 Gson So schliesen Sie bestimmte Felder ohne Anmerkungen von der
Nishant

Sie wollen also ausschließen firstName und country.name. Hier ist, was Ihr ExclusionStrategy Sollte aussehen, wie

    public class TestExclStrat implements ExclusionStrategy {

        public boolean shouldSkipClass(Class<?> arg0) {
            return false;
        }

        public boolean shouldSkipField(FieldAttributes f) {

            return (f.getDeclaringClass() == Student.class && f.getName().equals("firstName"))||
            (f.getDeclaringClass() == Country.class && f.getName().equals("name"));
        }

    }

Wenn Sie genau hinsehen, kehrt es zurück true zum Student.firstName und Country.namewas Sie ausschließen möchten.

Diese müssen Sie anwenden ExclusionStrategy so was,

    Gson gson = new GsonBuilder()
        .setExclusionStrategies(new TestExclStrat())
        //.serializeNulls() <-- uncomment to serialize NULL fields as well
        .create();
    Student src = new Student();
    String json = gson.toJson(src);
    System.out.println(json);

Dies gibt zurück:

{ "middleName": "J.", "initials": "P.F", "lastName": "Fry", "country": { "id": 91}}

Ich gehe davon aus, dass das Länderobjekt mit initialisiert wird id = 91L in der Schülerklasse.


Sie können Lust bekommen. Beispielsweise möchten Sie kein Feld serialisieren, das die Zeichenfolge „name“ in seinem Namen enthält. Mach das:

public boolean shouldSkipField(FieldAttributes f) {
    return f.getName().toLowerCase().contains("name"); 
}

Dies wird zurückgegeben:

{ "initials": "P.F", "country": { "id": 91 }}

BEARBEITEN: Weitere Informationen wie gewünscht hinzugefügt.

Dies ExclusionStrategy wird das Ding machen, aber Sie müssen “Fully Qualified Field Name” übergeben. Siehe unten:

    public class TestExclStrat implements ExclusionStrategy {

        private Class<?> c;
        private String fieldName;
        public TestExclStrat(String fqfn) throws SecurityException, NoSuchFieldException, ClassNotFoundException
        {
            this.c = Class.forName(fqfn.substring(0, fqfn.lastIndexOf(".")));
            this.fieldName = fqfn.substring(fqfn.lastIndexOf(".")+1);
        }
        public boolean shouldSkipClass(Class<?> arg0) {
            return false;
        }

        public boolean shouldSkipField(FieldAttributes f) {

            return (f.getDeclaringClass() == c && f.getName().equals(fieldName));
        }

    }

Hier ist, wie wir es allgemein verwenden können.

    Gson gson = new GsonBuilder()
        .setExclusionStrategies(new TestExclStrat("in.naishe.test.Country.name"))
        //.serializeNulls()
        .create();
    Student src = new Student();
    String json = gson.toJson(src);
    System.out.println(json); 

Es gibt zurück:

{ "firstName": "Philip" , "middleName": "J.", "initials": "P.F", "lastName": "Fry", "country": { "id": 91 }}

  • Vielen Dank für Ihre Antwort. Was ich möchte, ist eine ExclusionStrategy zu erstellen, die eine Zeichenfolge wie annehmen kann country.name und schließen nur das Feld aus name beim Serialisieren des Feldes country. Es sollte generisch genug sein, um auf jede Klasse angewendet zu werden, die eine Eigenschaft namens country der Country-Klasse hat. Ich möchte nicht für jede Klasse eine ExclusionStrategy erstellen

    – Liviu T.

    26. Januar 2011 um 11:59 Uhr

  • @Liviu T. Ich habe die Antwort aktualisiert. Das erfordert einen generischen Ansatz. Sie können noch kreativer werden, aber ich habe es elementar gehalten.

    – Nischant

    26. Januar 2011 um 12:48 Uhr

  • Ty für das Update. Was ich versuche zu sehen, ob es möglich ist zu wissen, wo ich mich im Objektdiagramm befinde, wenn die Methode aufgerufen wird, damit ich einige Länderfelder ausschließen kann, aber nicht countryOfBirth (zum Beispiel), also dieselbe Klasse, aber unterschiedliche Eigenschaften. Ich habe meine Frage bearbeitet, um zu verdeutlichen, was ich erreichen möchte

    – Liviu T.

    26. Januar 2011 um 15:08 Uhr

  • Gibt es eine Möglichkeit, Felder mit leeren Werten auszuschließen?

    – Yusuf K.

    21. Juli 2011 um 11:48 Uhr

  • Diese Antwort sollte als bevorzugte Antwort markiert werden. Im Gegensatz zu den anderen Antworten, die derzeit mehr Stimmen haben, müssen Sie bei dieser Lösung die Bean-Klasse nicht ändern. Dies ist ein großes Plus. Was wäre, wenn jemand anderes dieselbe Bean-Klasse verwendet und Sie ein Feld markiert haben, das er als “vorübergehend” beibehalten wollte?

    – Benutzer64141

    17. Juni 2015 um 0:18 Uhr

Nachdem ich alle verfügbaren Antworten gelesen hatte, fand ich heraus, dass es in meinem Fall am flexibelsten war, benutzerdefinierte zu verwenden @Exclude Anmerkung. Also habe ich dafür eine einfache Strategie implementiert (ich wollte nicht alle Felder mit markieren @Expose noch wollte ich verwenden transient was im Konflikt mit in App steht Serializable Serialisierung) :

Anmerkung:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Exclude {
}

Strategie:

public class AnnotationExclusionStrategy implements ExclusionStrategy {

    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return f.getAnnotation(Exclude.class) != null;
    }

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

Verwendungszweck:

new GsonBuilder().setExclusionStrategies(new AnnotationExclusionStrategy()).create();

Ich bin auf dieses Problem gestoßen, bei dem ich eine kleine Anzahl von Feldern hatte, die ich nur von der Serialisierung ausschließen wollte, also habe ich eine ziemlich einfache Lösung entwickelt, die Gsons verwendet @Expose Anmerkung mit benutzerdefinierten Ausschlussstrategien.

Die einzige integrierte Möglichkeit zu verwenden @Expose ist durch Einstellung GsonBuilder.excludeFieldsWithoutExposeAnnotation()aber wie der Name schon sagt, Felder ohne explizite @Expose werden ignoriert. Da ich nur wenige Felder hatte, die ich ausschließen wollte, fand ich die Aussicht, die Anmerkung zu jedem Feld hinzuzufügen, sehr umständlich.

Ich wollte effektiv die Umkehrung, in der alles enthalten ist, es sei denn, ich habe es ausdrücklich verwendet @Expose um es auszuschließen. Ich habe die folgenden Ausschlussstrategien verwendet, um dies zu erreichen:

new GsonBuilder()
        .addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                final Expose expose = fieldAttributes.getAnnotation(Expose.class);
                return expose != null && !expose.serialize();
            }

            @Override
            public boolean shouldSkipClass(Class<?> aClass) {
                return false;
            }
        })
        .addDeserializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                final Expose expose = fieldAttributes.getAnnotation(Expose.class);
                return expose != null && !expose.deserialize();
            }

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

Jetzt kann ich problemlos ein paar Felder mit ausschließen @Expose(serialize = false) oder @Expose(deserialize = false) Anmerkungen (beachten Sie, dass der Standardwert für beide @Expose Attribute ist true). Kannst du natürlich verwenden @Expose(serialize = false, deserialize = false)aber das wird präziser erreicht, indem das Feld deklariert wird transient stattdessen (was bei diesen benutzerdefinierten Ausschlussstrategien immer noch wirksam ist).

  • Aus Effizienzgründen sehe ich einen Fall für die Verwendung von @Expose (serialize = false, deserialize = false) anstelle von transient.

    – paiego

    23. August 2018 um 18:12 Uhr

  • @paiego Kannst du darauf eingehen? Ich bin jetzt viele Jahre von der Verwendung von Gson entfernt und verstehe nicht, warum die Anmerkung effizienter ist, als sie vorübergehend zu markieren.

    – Derek Shockey

    23. August 2018 um 22:22 Uhr

  • Ahh, ich habe einen Fehler gemacht, danke, dass du das aufgefangen hast. Ich habe flüchtig mit vorübergehend verwechselt. (z. B. Es gibt kein Caching und daher kein Cache-Kohärenzproblem mit volatile, aber es ist weniger leistungsfähig) Wie auch immer, Ihr Code hat großartig funktioniert!

    – paiego

    11. September 2018 um 20:48 Uhr


1646258232 657 Gson So schliesen Sie bestimmte Felder ohne Anmerkungen von der
Claudia Rzewnicka

Sie können den json-Baum mit gson erkunden.

Versuchen Sie so etwas:

gson.toJsonTree(student).getAsJsonObject()
.get("country").getAsJsonObject().remove("name");

Sie können auch einige Eigenschaften hinzufügen:

gson.toJsonTree(student).getAsJsonObject().addProperty("isGoodStudent", false);

Getestet mit gson 2.2.4.

  • Aus Effizienzgründen sehe ich einen Fall für die Verwendung von @Expose (serialize = false, deserialize = false) anstelle von transient.

    – paiego

    23. August 2018 um 18:12 Uhr

  • @paiego Kannst du darauf eingehen? Ich bin jetzt viele Jahre von der Verwendung von Gson entfernt und verstehe nicht, warum die Anmerkung effizienter ist, als sie vorübergehend zu markieren.

    – Derek Shockey

    23. August 2018 um 22:22 Uhr

  • Ahh, ich habe einen Fehler gemacht, danke, dass du das aufgefangen hast. Ich habe flüchtig mit vorübergehend verwechselt. (z. B. Es gibt kein Caching und daher kein Cache-Kohärenzproblem mit volatile, aber es ist weniger leistungsfähig) Wie auch immer, Ihr Code hat großartig funktioniert!

    – paiego

    11. September 2018 um 20:48 Uhr


1646258233 45 Gson So schliesen Sie bestimmte Felder ohne Anmerkungen von der
Dominik D.

Ich habe mir eine Klassenfabrik ausgedacht, um diese Funktionalität zu unterstützen. Übergeben Sie eine beliebige Kombination von Feldern oder Klassen, die Sie ausschließen möchten.

public class GsonFactory {

    public static Gson build(final List<String> fieldExclusions, final List<Class<?>> classExclusions) {
        GsonBuilder b = new GsonBuilder();
        b.addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                return fieldExclusions == null ? false : fieldExclusions.contains(f.getName());
            }

            @Override
            public boolean shouldSkipClass(Class<?> clazz) {
                return classExclusions == null ? false : classExclusions.contains(clazz);
            }
        });
        return b.create();

    }
}

Erstellen Sie zur Verwendung zwei Listen (jeweils optional) und erstellen Sie Ihr GSON-Objekt:

static {
 List<String> fieldExclusions = new ArrayList<String>();
 fieldExclusions.add("id");
 fieldExclusions.add("provider");
 fieldExclusions.add("products");

 List<Class<?>> classExclusions = new ArrayList<Class<?>>();
 classExclusions.add(Product.class);
 GSON = GsonFactory.build(null, classExclusions);
}

private static final Gson GSON;

public String getSomeJson(){
    List<Provider> list = getEntitiesFromDatabase();
    return GSON.toJson(list);
}

  • Natürlich kann dies geändert werden, um den vollständig qualifizierten Namen des Attributs zu betrachten und diesen bei einer Übereinstimmung auszuschließen …

    – Domenik D.

    26. April 2012 um 18:07 Uhr

  • Ich mache das folgende Beispiel. Das funktioniert nicht. Bitte schlagen Sie privates statisches letztes Gson GSON vor; statisch { List fieldExclusions = new ArrayList(); fieldExclusions.add(“id”); GSON = GsonFactory.build (fieldExclusions, null); } privater statischer String getSomeJson() { String jsonStr = “[{\”id\”:111,\”name\”:\”praveen\”,\”age\”:16},{\”id\”:222,\”name\”:\”prashant\”,\”age\”:20}]”; jsonStr zurückgeben; } public static void main(String[] args) {String jsonStr = getSomeJson(); System.out.println(GSON.toJson(jsonStr)); }

    – Praveen Hiremath

    30. August 2016 um 6:53 Uhr


916530cookie-checkGson: So schließen Sie bestimmte Felder ohne Anmerkungen von der Serialisierung aus

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

Privacy policy