I'm versuchen, Gson zu lernen und I'm kämpfen mit Feld Ausschluss. 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 Vorname
oder Land
hinzufügen, aber ich scheine es nicht zu schaffen, Eigenschaften bestimmter Felder wie Land.name
auszuschließen.
Wenn ich die Methode public boolean shouldSkipField(FieldAttributes fa)
verwende, enthält FieldAttributes nicht genug Informationen, um das Feld mit einem Filter wie country.name
abzugleichen.
Ich wäre dankbar für jede Hilfe bei der Lösung dieses Problems.
P.S.: Ich möchte Annotationen vermeiden, da ich dies verbessern und RegEx zum Herausfiltern von Feldern verwenden möchte.
Dankeschön
Edit: Ich versuche zu sehen, ob es möglich ist, das Verhalten von Struts2 JSON plugin zu emulieren.
mit Gson
<interceptor-ref name="json">
<param name="enableSMD">true</param>
<param name="excludeProperties">
login.password,
studentList.*\.sin
</param>
</interceptor-ref>
Edit: Ich habe die Frage mit dem folgenden Zusatz wieder geöffnet:
Ich habe ein zweites Feld mit demselben Typ hinzugefügt, um das Problem weiter zu klären. Grundsätzlich möchte ich Land.Name
ausschließen, aber nicht Geburtszahl.Name
. Ich möchte auch nicht Land als Typ ausschließen.
Die Typen sind also die gleichen, es ist die tatsächliche Stelle im Objektgraphen, die ich herausfinden und ausschließen möchte.
Alle Felder, die Sie nicht serialisiert haben wollen, sollten Sie mit dem Modifikator "transient" versehen. Dies gilt auch für json-Serialisierer (zumindest für einige, die ich verwendet habe, einschließlich gson).
Wenn Sie nicht wollen, dass der Name im serialisierten json auftaucht, geben Sie ihm ein transientes Schlüsselwort, z.B.:
private transient String name;
Nishant hat eine gute Lösung gefunden, aber es gibt einen einfacheren Weg. Markieren Sie einfach die gewünschten Felder mit der @Expose-Anmerkung, wie z. B.:
@Expose private Long id;
Lassen Sie alle Felder weg, die Sie nicht serialisieren wollen. Dann erstellen Sie Ihr Gson-Objekt einfach auf diese Weise:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Sie möchten also den "Vornamen" und den "Landesnamen" ausschließen. So sollte Ihre ExclusionStrategy
aussehen
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, gibt sie true
für Student.firstName
und Country.name
zurück, also das, was Sie ausschließen wollen.
Sie müssen diese ExclusionStrategy
wie folgt anwenden,
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 in der Schülerklasse mit id = 91L
initialisiert wird.
Sie können sich etwas einfallen lassen. Sie möchten zum Beispiel kein Feld serialisieren, das die Zeichenfolge "name" in seinem Namen enthält. Tun Sie dies:
public boolean shouldSkipField(FieldAttributes f) {
return f.getName().toLowerCase().contains("name");
}
Dies wird zurückgegeben:
{ "initials": "P.F", "country": { "id": 91 }}
EDIT: Weitere Informationen wie gewünscht hinzugefügt.
Diese ExclusionStrategy
wird die Sache erledigen, 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 generisch 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 }}