„Gson“: kaip išskirti tam tikrus laukus iš serializavimo be komentarų

Bandau išmokti Gsoną, ir aš kovoju su lauko išskyrimu. Čia yra mano klasės

 public class Student { private Long id; private String firstName = "Philip"; private String middleName = "J."; private String initials = "PF"; private String lastName = "Fry"; private Country country; private Country countryOfBirth; } public class Country { private Long id; private String name; private Object other; } 

Galiu naudoti „GsonBuilder“ ir pridėti „ExclusionStrategy“ už lauko pavadinimą, pvz., „ firstName arba country , bet man atrodo, kad negaliu išskirti tam tikrų laukų savybių, pvz., firstName .

Naudojant public boolean shouldSkipField(FieldAttributes fa) metodą, „ public boolean shouldSkipField(FieldAttributes fa) ,„ FieldAttributes “nėra pakankamai informacijos, kad atitiktų filtro lauką, pvz., Country.name.

Būčiau dėkingas už pagalbą sprendžiant šią problemą.

PS: noriu išvengti anotacijų, nes noriu ją patobulinti ir naudoti RegEx filtravimo laukams.

Ačiū

Keisti . Bandau suprasti, ar galima sekti Struts2 JSON įskiepio elgesį

naudojant „gson“

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

Redaguoti: dar kartą atidariau šį klausimą:

Šiai problemai išsiaiškinti pridėjau antrą lauką su tuo pačiu tipu. Iš esmės, aš noriu išskirti country.name , bet ne countrOfBirth.name . Taip pat nenoriu šalį šalinti kaip tipą. Taigi tipai yra tos pačios faktinės vietos objektų diagramoje, kurią noriu tiksliai apibrėžti ir išskirti.

355
26 янв. nustatė Liviu T. 26 Jan. 2011-01-26 12:19 '11, 12:19, 2011-01-26 12:19
@ 12 atsakymų

Visi laukai, kurių nenorite serializuoti, turėtų naudoti „pereinamojo laikotarpio“ modifikatorių, ir tai taip pat taikoma „Json“ serializatoriams (bent jau tai taikoma keliems, kuriuos naudoju, įskaitant „gson“).

Jei nenorite, kad pavadinimas būtų rodomas serializuotame „Json“, suteikite jam laikiną raktinį žodį, pavyzdžiui:

 private transient String name; 

Skaitykite daugiau „Gson“ dokumentuose.

561
04 мая '11 в 23:40 2011-05-04 23:40 atsakymą pateikė Chris Seline , gegužės 4 d., 11 d., 23:40 2011-05-04 23:40

„Nishant“ pateikė gerą sprendimą, tačiau buvo lengviau. Tiesiog pažymėkite reikiamus laukus su @Expose anotacija, pavyzdžiui:

 @Expose private Long id; 

Palikite visus laukus, kurių nenorite serializuoti. Tada tiesiog sukurkite tokį „Gson“ objektą:

 Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); 
288
18 окт. JayPea atsakymas spalio 18 d 2011-10-18 20:26 '11, 20:26, 2011-10-18 20:26

Taigi jūs norite pašalinti firstName ir šalies pavadinimą. Štai kaip atrodo „ ExclusionStrategy .

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

Jei matote, būtent jis grįš „ Student.firstName ir „ Student.firstName , kuris yra tas, kurį norite pašalinti.

Jums reikia taikyti šią ExclusionStrategy ,

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

Tai grąžina:

{"MiddleName": "J", "inicialai": "PF", "LastName": "Fry", "country": {"ID": 91}}

Darau prielaidą, kad šalies objektas yra inicijuojamas id = 91L studentų klasėje.


Galite gauti fantaziją. Pvz., Nenorite serializuoti jokių laukų, turinčių pavadinimą. Ar tai:

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

Tai grąžins:

 { "initials": "PF", "country": { "id": 91 }} 

EDIT: paprašius pridėta daugiau informacijos.

Ši „ ExclusionStrategy tai padarys, bet jums reikia perduoti „visiškai kvalifikuotą lauko pavadinimą“. Žiūrėkite žemiau:

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

Štai kaip mes galime jį naudoti kaip visumą.

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

Ji grąžina:

 { "firstName": "Philip" , "middleName": "J.", "initials": "PF", "lastName": "Fry", "country": { "id": 91 }} 
208
26 янв. atsakymą Nishant pateikė sausio 26 d. 2011-01-26 13:13 '11, 13:13, 2011-01-26 13:13

Perskaitęs visus turimus atsakymus, sužinojau, kad lanksčiausi, mano nuomone, buvo naudoti „ @Exclude naudotojo komentarus. Taigi įgyvendinau paprastą strategiją (nenorėjau pažymėti visų laukų naudodamas „ @Expose , ir nenorėjau naudoti transient , kuris prieštarautų „ Serializable programos Serializable ):

Anotacija:

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

Strategija:

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

Naudoti:

 new GsonBuilder().setExclusionStrategies(new AnnotationExclusionStrategy()).create(); 
175
16 янв. atsakymas duotas pkk 16 sausis 2015-01-16 18:04 '15, 18:04 2015-01-16 18:04

Aš susidūriau su šia problema, kurioje turėjau nedidelį skaičių laukų, kuriuos norėjau išskirti tik iš serializacijos, todėl sukūriau gana paprastą sprendimą, kuris naudoja „Gson @Expose komentarą su pasirinktinėmis išskyrimo strategijomis.

Vienintelis @Expose būdas naudoti „ @Expose yra nustatyti „ GsonBuilder.excludeFieldsWithoutExposeAnnotation() , tačiau, kaip rodo pavadinimas, laukai, kuriuose nėra aiškios „ @Expose ignoruojami. Kadangi aš turėjau tik keletą sričių, kurias norėjau išskirti, pastebėjau, kad kiekvienai sričiai pridėti anotacijų labai sudėtinga.

Man tikrai reikia atvirkštinio, kuriame viskas buvo įtraukta, nebent aš aiškiai naudoju @Expose , kad jį pašalintume. Tam naudoju šias išskyrimo strategijas:

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

Dabar galiu lengvai išskirti kelis laukus, pažymėtus su @Expose(serialize = false) arba @Expose(deserialize = false) (atkreipkite dėmesį, kad numatytoji reikšmė abiem @Expose atributams yra true ). Žinoma, galite naudoti „ @Expose(serialize = false, deserialize = false) , tačiau tai tiksliau pasiekiama deklaruojant transient lauką (kuris vis dar įsigalioja su šiomis pasirinktinėmis išimčių strategijomis).

73
18 июля '13 в 23:46 2013-07-18 23:46 atsakymą pateikė Derek Shockey, liepos 18 d., 13 val. 11:46 2013-07-18 23:46

Šiai funkcijai palaikyti sukūriau gamyklos klasę. Praleiskite bet kokį laukų ar klasių derinį, kurį norite pašalinti.

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

Jei norite naudoti, sukurkite du sąrašus (kiekvienas neprivalomas) ir sukurkite savo 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); } 
16
26 апр. atsakymą pateikė Domenic D. 26 Bal. 2012-04-26 21:03 '12, 21:03 2012-04-26 21:03

Jsoną galite ištirti gsonu.

Išbandykite tai:

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

Taip pat galite pridėti keletą savybių:

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

Išbandyta su žandikauliu 2.2.4.

15
06 февр. Atsakymą pateikė Klaudia Rzewnicka vasario 6 d. 2014-02-06 11:16 '14, 11:16 AM 2014-02-06 11:16

Aš išsprendžiau šią problemą su specialiomis anotacijomis. Tai mano komentarų klasė „SkipSerialisation“:

 @Target (ElementType.FIELD) public @interface SkipSerialisation { } 

ir tai yra mano „GsonBuilder“:

 gsonBuilder.addSerializationExclusionStrategy(new ExclusionStrategy() { @Override public boolean shouldSkipField (FieldAttributes f) { return f.getAnnotation(SkipSerialisation.class) != null; } @Override public boolean shouldSkipClass (Class<?> clazz) { return false; } }); 

Pavyzdys:

 public class User implements Serializable { public String firstName; public String lastName; @SkipSerialisation public String email; } 
12
12 сент. Atsakymą pateikė Reyske 12 sep . 2016-09-12 12:35 '16 at 12:35 pm 2016-09-12 12:35

Arba galite nurodyti, kurie laukai nebus rodomi su:

 Gson gson = gsonBuilder.excludeFieldsWithModifiers(Modifier.TRANSIENT).create(); 

pagal savo klasę pagal atributą:

 private **transient** boolean nameAttribute; 
8
02 июня '13 в 23:42 2013-06-02 23:42 atsakymą pateikė lucasddaniel birželio 13 d . 13:42 2013-06-02 23:42

Kitas metodas (ypač naudingas, jei reikia nuspręsti neįtraukti lauko vykdymo metu) yra Tipo adapterio registravimas su savo gsono pavyzdžiu. Toliau pateiktas pavyzdys:

 Gson gson = new GsonBuilder() .registerTypeAdapter(BloodPressurePost.class, new BloodPressurePostSerializer()) 

Tokiu atveju serveris tikisi vieno iš dviejų vertybių, tačiau, kadangi abi jos buvo int, tuomet gsonas bus abu. Mano tikslas buvo praleisti bet kokią vertę, kuri yra nulis (ar mažiau) iš serverio siunčiamo „Json“.

 public class BloodPressurePostSerializer implements JsonSerializer<BloodPressurePost> { @Override public JsonElement serialize(BloodPressurePost src, Type typeOfSrc, JsonSerializationContext context) { final JsonObject jsonObject = new JsonObject(); if (src.systolic > 0) { jsonObject.addProperty("systolic", src.systolic); } if (src.diastolic > 0) { jsonObject.addProperty("diastolic", src.diastolic); } jsonObject.addProperty("units", src.units); return jsonObject; } } 
6
27 авг. atsakymas duotas Damianui 27 d. 2015-08-27 16:53 '15 at 16:53 2015-08-27 16:53

Naudojau šią strategiją: pašalinau kiekvieną lauką, kuris nėra pažymėtas @SerializedName anotacija, ty:

 public class Dummy { @SerializedName("VisibleValue") final String visibleValue; final String hiddenValue; public Dummy(String visibleValue, String hiddenValue) { this.visibleValue = visibleValue; this.hiddenValue = hiddenValue; } } public class SerializedNameOnlyStrategy implements ExclusionStrategy { @Override public boolean shouldSkipField(FieldAttributes f) { return f.getAnnotation(SerializedName.class) == null; } @Override public boolean shouldSkipClass(Class<?> clazz) { return false; } } Gson gson = new GsonBuilder() .setExclusionStrategies(new SerializedNameOnlyStrategy()) .create(); Dummy dummy = new Dummy("I will see this","I will not see this"); String json = gson.toJson(dummy); 

Jis grįžta

{"VisibleValue": "Aš jį matysiu"}

5
20 июля '16 в 15:15 2016-07-20 15:15 atsakymas duotas MadMurdok liepos 20 d. 16, 15:15 2016-07-20 15:15

Dirbu, paprasčiausiai pateikdamas „ @Expose komentarą, čia yra mano versija, kurią naudoju

 compile 'com.squareup.retrofit2:retrofit:2.0.2' compile 'com.squareup.retrofit2:converter-gson:2.0.2' 

Model klasėje:

 @Expose int number; public class AdapterRestApi { 

Adapter klasėje:

 public EndPointsApi connectRestApi() { OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(90000, TimeUnit.SECONDS) .readTimeout(90000,TimeUnit.SECONDS).build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(ConstantRestApi.ROOT_URL) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build(); return retrofit.create (EndPointsApi.class); } 
0
31 марта '17 в 19:26 2017-03-31 19:26 atsakymas duotas devitoper kovo 31 d. 17, 19:26 2017-03-31 19:26