
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.

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

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

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.name
was 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 }}
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).

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.

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);
}
9165300cookie-checkGson: So schließen Sie bestimmte Felder ohne Anmerkungen von der Serialisierung ausyes
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 wirdExclusionStrategy
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