Gson: एनोटेशन के बिना सीरियल से विशिष्ट क्षेत्रों को बाहर कैसे करें


413

मैं Gson सीखने की कोशिश कर रहा हूँ और मैं क्षेत्र बहिष्कार से जूझ रहा हूँ। यहाँ मेरी कक्षाएं हैं

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

मैं GsonBuilder का उपयोग करें और की तरह एक फ़ील्ड नाम के लिए एक ExclusionStrategy जोड़ सकते हैं firstNameया countryलेकिन मैं जैसे कुछ क्षेत्रों के गुणों को बाहर करने का प्रबंधन नहीं कर पा रहे country.name

विधि का उपयोग करते हुए public boolean shouldSkipField(FieldAttributes fa), FieldAttributes में फ़िल्टर जैसे फ़ील्ड से मिलान करने के लिए पर्याप्त जानकारी नहीं होती है country.name

पुनश्च: मैं एनोटेशन से बचना चाहता हूं क्योंकि मैं इस पर सुधार करना चाहता हूं और खेतों को छानने के लिए RegEx का उपयोग करता हूं।

संपादित करें : मैं यह देखने की कोशिश कर रहा हूं कि क्या Struts2 JSON प्लगइन के व्यवहार का अनुकरण करना संभव है

Gson का उपयोग कर

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

संपादित करें: मैंने प्रश्न को निम्नलिखित जोड़ के साथ फिर से खोल दिया:

मैंने इस समस्या को स्पष्ट करने के लिए उसी प्रकार के साथ एक दूसरा क्षेत्र जोड़ा। मूल रूप से मैं बाहर करना चाहता हूं country.nameलेकिन नहीं countrOfBirth.name। मैं भी एक प्रकार के रूप में देश को बाहर नहीं करना चाहता। तो प्रकार समान हैं यह ऑब्जेक्ट ग्राफ में वास्तविक स्थान है जिसे मैं इंगित करना चाहता हूं और बाहर करना चाहता हूं।


1
संस्करण 2.2 के रूप में अभी भी मैं अभी भी बाहर करने के लिए क्षेत्र के लिए एक पथ निर्दिष्ट नहीं कर सकता। flexjson.sourceforge.net एक अच्छा विकल्प लगता है।
लिविउ टी।

मेरे जवाब पर एक नज़र एक बहुत ही इसी तरह के सवाल पर है। यह JsonSerializerकुछ प्रकार के लिए एक प्रथा बनाने पर आधारित है - Countryआपके मामले में - जिसके लिए फिर एक आवेदन किया जाता है ExclusionStrategyजो यह तय करता है कि किस क्षेत्र को क्रमबद्ध करना है।
पिरहो

जवाबों:


625

कोई भी क्षेत्र जिसे आप सामान्य रूप से क्रमबद्ध नहीं करना चाहते हैं, आपको "क्षणिक" संशोधक का उपयोग करना चाहिए, और यह जौनस धारावाहिकों पर भी लागू होता है (कम से कम यह कुछ है जो मैंने उपयोग किया है, जिसमें गन्स भी शामिल है)।

यदि आप नाम नहीं दिखाना चाहते हैं तो क्रमबद्ध जोंस में यह एक क्षणिक खोजशब्द है, उदाहरणार्थ:

private transient String name;

Gson प्रलेखन में अधिक जानकारी


6
यह बहिष्करण एनोटेशन के रूप में लगभग एक ही बात है क्योंकि यह उस वर्ग के सभी उदाहरणों पर लागू होता है। मैं रनटाइम डायनेमिक एक्सक्लूजन चाहता था। कुछ मामलों में मैं कुछ क्षेत्रों को एक हल्का / प्रतिबंधित प्रतिक्रिया प्रदान करने के लिए बाहर रखा जाना चाहता हूं और अन्य में मैं पूरी वस्तु को क्रमबद्ध करना चाहता हूं
Liviu T.

34
ध्यान देने वाली एक बात यह है कि क्षणिक प्रभाव धारावाहिकीकरण और deserialization दोनों को प्रभावित करता है। यह ऑब्जेक्ट में क्रमबद्ध रूप से मान को भी उत्सर्जित करेगा, भले ही वह JSON में मौजूद हो।
काँग

3
इसके transientबजाय का उपयोग करने के साथ समस्या यह @Exposeहै कि आपको अभी भी अपने क्लाइंट पर सभी क्षेत्रों के साथ एक POJO का मजाक उड़ाना होगा जो संभवतः अंदर आ सकते हैं। बैक-एंड एपीआई के मामले में जिसे परियोजनाओं के बीच साझा किया जा सकता है, यह समस्याग्रस्त हो सकता है। अतिरिक्त फ़ील्ड जोड़े जाते हैं। अनिवार्य रूप से यह खेतों की ब्लैकलिस्टिंग बनाम व्हाइटलाइटिंग है।
17

11
इस दृष्टिकोण ने मेरे लिए काम नहीं किया, क्योंकि इसने न केवल फील्ड को गैन्स सीरियलाइज़ेशन से बाहर रखा, बल्कि इंटरनल ऐप सीरियलाइज़ेशन (सीरियलाइज़ेबल इंटरफ़ेस का उपयोग करके) से फ़ील्ड को बाहर कर दिया।
पीके

8
क्षणिक एक क्षेत्र के क्रमिक और विचलन को रोकता है। यह मेरी जरूरतों से मेल नहीं खाता।
लोएनिक्स

318

निशांत ने एक अच्छा समाधान प्रदान किया, लेकिन एक आसान तरीका है। बस @Exuse एनोटेशन के साथ वांछित फ़ील्ड चिह्नित करें, जैसे:

@Expose private Long id;

ऐसे किसी भी क्षेत्र को छोड़ दें, जिसे आप क्रमबद्ध नहीं करना चाहते हैं। तो बस इस तरह से अपने Gson ऑब्जेक्ट बनाएँ:

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

95
क्या "notExpose" जैसा कुछ होना संभव है और केवल उन मामलों के लिए उपेक्षा करें जहां सभी लेकिन एक क्षेत्र को क्रमांकित किया जाना चाहिए और उन सभी में एनोटेशन जोड़ना बेमानी है?
डेनियल शेवलेव

2
@DaSh मैंने हाल ही में ऐसा परिदृश्य देखा था। एक कस्टम एक्सक्लूजनस्ट्रेरी लिखना बहुत आसान था जो वास्तव में ऐसा ही करता था। देखें निशांत का जवाब एकमात्र समस्या कंटेनर वर्गों का एक झुंड और स्किपक्लास बनाम स्किपफील्ड (फ़ील्ड्स वर्ग हो सकती है ...) के साथ शामिल थी
कीसर

1
@DaSh मेरा जवाब नीचे दिया गया है।
डेरेक हॉकी

क्या शानदार उपाय है। मैं एक ऐसे परिदृश्य में चल रहा था, जहाँ मैं डिस्क पर क्रमबद्ध फ़ील्ड चाहता हूँ, लेकिन इसे सर्वर पर भेजने के दौरान अनदेखा किया जा सकता है। बहुत बहुत धन्यवाद!

1
@ डनलिल आपको @ एक्सपोज (क्रमबद्ध = गलत,
डिस्क्रिअलाइज

237

तो, आप बहिष्कृत करना चाहते हैंfirstName और country.name। यहाँ वही है जो आपकी 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"));
        }

    }

यदि आप निकट से देखते हैं तो यह और के trueलिए लौटता हैStudent.firstNameCountry.name है, जो है क्या आप छोड़ना चाहते हैं।

आपको इसे इस 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);

यह रिटर्न:

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

मुझे लगता है कि id = 91Lछात्र वर्ग में देश की वस्तु का आरंभ होता है।


आपको फैंसी मिल सकती है। उदाहरण के लिए, आप किसी भी फ़ील्ड को क्रमबद्ध नहीं करना चाहते हैं जिसमें उसके नाम में "नाम" स्ट्रिंग हो। यह करो:

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

यह लौटेगा:

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

संपादित करें: अनुरोध के अनुसार अधिक जानकारी जोड़ी गई।

यह ExclusionStrategyबात करेगा, लेकिन आपको "पूरी तरह से योग्य फ़ील्ड नाम" पास करने की आवश्यकता है। निचे देखो:

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

    }

यहां बताया गया है कि हम इसे उदारतापूर्वक कैसे उपयोग कर सकते हैं।

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

यह रिटर्न:

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

जवाब देने के लिए धन्यवाद। मैं जो चाहता हूं वह एक एक्सक्लूज़नस्ट्रेगी बनाना है जो एक स्ट्रिंग की तरह ले सकता है country.nameऔर केवल क्षेत्र nameको क्रमबद्ध करते समय फ़ील्ड को बाहर कर सकता है country। यह प्रत्येक वर्ग के लिए लागू करने के लिए पर्याप्त सामान्य होना चाहिए, जिसके पास देश श्रेणी का देश नाम की संपत्ति है। मैं हर वर्ग के लिए एक बहिष्करणस्ट्रीमेटी नहीं बनाना चाहता
Liviu T.

@ लिविउ टी। मैंने जवाब अपडेट कर दिया है। यह सामान्य दृष्टिकोण लेता है। आप और भी अधिक रचनात्मक हो सकते हैं, लेकिन मैंने इसे तात्विक रखा।
निशांत

अद्यतन के लिए Ty। मैं क्या देख रहा हूँ, यह देखने की कोशिश कर रहा हूँ कि वस्तु ग्राफ में मैं कहाँ हूँ, जब यह विधि कहलाती है तो मैं देश के कुछ क्षेत्रों को छोड़ सकता हूँ, लेकिन देश के आधार पर नहीं (उदाहरण के लिए) एक ही वर्ग लेकिन अलग-अलग गुण। मैंने अपने प्रश्न को यह स्पष्ट करने के लिए संपादित किया है कि मैं क्या हासिल करने की कोशिश कर रहा हूं
Liviu T.

क्या उन क्षेत्रों को बाहर करने का एक तरीका है जिनमें खाली मूल्य हैं?
युसुफ के।

12
इस उत्तर को पसंदीदा उत्तर के रूप में चिह्नित किया जाना चाहिए। वर्तमान में अधिक वोटों वाले अन्य उत्तरों के विपरीत, इस समाधान के लिए आपको बीन क्लास को संशोधित करने की आवश्यकता नहीं है। यह बहुत बड़ा प्लस है। क्या होगा यदि कोई और उसी सेम क्लास का उपयोग कर रहा है, और आपने एक फ़ील्ड चिह्नित किया है जिसे वे "क्षणिक" के रूप में बनाए रखना चाहते हैं?
user64141

221

सभी उपलब्ध उत्तरों को पढ़ने के बाद, मुझे पता चला कि मेरे मामले में सबसे अधिक लचीला, कस्टम @Excludeएनोटेशन का उपयोग करना था । इसलिए, मैंने इसके लिए सरल रणनीति को लागू किया (मैं सभी क्षेत्रों का उपयोग नहीं करना @Exposeचाहता था और न ही मैं उपयोग करना चाहता था कि transientऐप में किसके साथ विवाद हुआSerializable क्रमांकन किसके ):

एनोटेशन:

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

रणनीति:

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

उपयोग:

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

16
एक अतिरिक्त नोट के रूप में, यदि आप केवल क्रमांकन या केवल addSerializationExclusionStrategyaddDeserializationExclusionStrategysetExclusionStrategies
डीरियलाइज़ेशन के

9
उत्तम! क्षणिक समाधान मेरे लिए काम नहीं करता है क्योंकि मैं DB के लिए Realm का उपयोग कर रहा हूं और मैं केवल Gson से एक क्षेत्र को बाहर करना चाहता हूं, लेकिन Realm नहीं (wich transient करता है)
Marcio Granzotto

3
यह स्वीकृत उत्तर होना चाहिए। अनदेखी करने के लिए अशक्त क्षेत्रों बस बदलने f.getAnnotation(Exclude.class) != nullके लिएf.getAnnotation(Exclude.class) == null
तेज धार

3
उत्कृष्ट जब आप transientअन्य पुस्तकालयों की जरूरतों के कारण उपयोग नहीं कर सकते हैं। धन्यवाद!
मार्टिन डी

1
मेरे लिए भी बहुत अच्छा है क्योंकि एंड्रॉइड गतिविधियों के बीच मेरी कक्षाओं को क्रमबद्ध करता है, लेकिन मैं केवल उन्हें चाहता हूं जब मैं जीएसओएन का उपयोग करता हूं। चलो यह मेरा ऐप उसी तरह से काम करता है जब तक कि वह दूसरों को भेजने के लिए उन्हें लपेटना नहीं चाहता।
thePartyTurtle

81

मैं इस मुद्दे पर भाग गया, जिसमें मेरे पास बहुत कम क्षेत्र थे जिन्हें मैं केवल क्रमांकन से बाहर करना चाहता था, इसलिए मैंने एक बहुत ही सरल समाधान विकसित किया जो ग्सन का उपयोग करता है @Expose कस्टम अपवर्जन रणनीतियों के साथ एनोटेशन ।

उपयोग करने के लिए केवल अंतर्निहित तरीका @Exposeसेटिंग द्वारा है GsonBuilder.excludeFieldsWithoutExposeAnnotation(), लेकिन जैसा कि नाम से पता चलता है, स्पष्ट बिना फ़ील्ड@Expose को अनदेखा किया जाता है। जैसा कि मेरे पास केवल कुछ क्षेत्र थे जिन्हें मैं बाहर करना चाहता था, मुझे एनोटेशन को हर क्षेत्र में जोड़ने की संभावना बहुत बोझिल लग रही थी।

मैं प्रभावी रूप से उलटा चाहता था, जिसमें सब कुछ शामिल था जब तक कि मैं स्पष्ट रूप @Exposeसे इसे बाहर करने के लिए उपयोग नहीं करता था। इसे पूरा करने के लिए मैंने निम्नलिखित बहिष्करण रणनीतियों का उपयोग किया:

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

अब मैं आसानी से @Expose(serialize = false)या @Expose(deserialize = false)एनोटेशन के साथ कुछ क्षेत्रों को बाहर कर सकता हूं (ध्यान दें कि दोनों @Exposeविशेषताओं के लिए डिफ़ॉल्ट मान है true)। आप निश्चित रूप से उपयोग कर सकते हैं @Expose(serialize = false, deserialize = false), लेकिन यह transientइसके बजाय क्षेत्र को घोषित करके अधिक संक्षिप्त रूप से पूरा किया जाता है (जो अभी भी इन कस्टम अपवर्जन के साथ प्रभावी होता है)।


दक्षता के लिए, मैं क्षणिक के बजाय @Expose (serialize = false, deserialize = false) का उपयोग करने के लिए एक मामला देख सकता हूं।
पेइगो

1
क्या आप उस पर विस्तार कर सकते हैं? मुझे अब Gson का उपयोग करने से कई साल दूर हो गए हैं, और मुझे समझ में नहीं आता है कि एनोटेशन इसे क्षणिक चिह्नित करने की तुलना में अधिक कुशल क्यों है।
डेरेक हॉकी

आह, मैंने एक गलती की, इसे पकड़ने के लिए धन्यवाद। मैंने क्षणिक के लिए अस्थिरता को गलत समझा। (उदा। कोई कैशिंग नहीं है और इसलिए अस्थिर के साथ कोई कैश-सुसंगति समस्या नहीं है, लेकिन यह कम प्रदर्शन वाला है) वैसे भी, आपके कोड ने बहुत अच्छा काम किया है!
पैगीगो

18

आप गॉन के साथ जौन के पेड़ का पता लगा सकते हैं।

कुछ इस तरह की कोशिश करो:

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

आप कुछ गुण भी जोड़ सकते हैं:

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

गसन 2.2.4 के साथ परीक्षण किया गया।


3
मुझे आश्चर्य है कि क्या यह बहुत अधिक प्रदर्शन हिट है यदि आप एक जटिल संपत्ति से छुटकारा चाहते हैं जिसे हटाने से पहले पार्स किया जाना है। विचार?
बेन

निश्चित रूप से एक स्केलेबल समाधान नहीं है, सभी सिरदर्द की कल्पना करें यदि आपको अपनी वस्तु की संरचना को बदलना है या सामान जोड़ना / हटाना है।
codenamezero

16

मैं इस कार्यक्षमता का समर्थन करने के लिए एक वर्ग कारखाने के साथ आया था। उन क्षेत्रों या कक्षाओं के किसी भी संयोजन में पास करें जिन्हें आप बाहर करना चाहते हैं।

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

    }
}

उपयोग करने के लिए, दो सूचियां बनाएं (प्रत्येक वैकल्पिक है), और अपना GSON ऑब्जेक्ट बनाएं:

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

बेशक, यह विशेषता के पूरी तरह से योग्य नाम को देखने के लिए संशोधित किया जा सकता है और एक मैच से बाहर कर सकता है ...
डोमिनिक डी।

मैं नीचे उदाहरण के लिए कर रहा हूँ। ये काम नहीं कर रहा है। Pls निजी स्थिर अंतिम Gson GSON का सुझाव दें; स्थिर {सूची <string> fieldExclusions = new ArrayList <string> (); fieldExclusions.add ( "आईडी"); GSON = GsonFactory.build (fieldExclusions, null); } निजी स्थिर स्ट्रिंग getSomeJson () {स्ट्रिंग jsonStr = "[{\" id \ ": 111, \" name \ ": \" praveen \ ", \" age \ ": 16}, {\" id \ ": 222, \ "नाम \": \ "प्रशांत \", \ "उम्र \": 20}] "; वापसी jsonStr; } public static void main (स्ट्रिंग [] args) {स्ट्रिंग jsonStr = getSomeJson (); Println (GSON.toJson (jsonStr)); }
प्रवीण हिरेमथ

13

मैंने कस्टम एनोटेशन के साथ इस समस्या को हल किया। यह मेरा "SkipSerialisation" एनोटेशन वर्ग है:

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

}

और यह मेरा 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;
  }
});

उदाहरण :

public class User implements Serializable {

  public String firstName;

  public String lastName;

  @SkipSerialisation
  public String email;
}

5
Gson: एनोटेशन के बिना
बेन

3
आपको @Retention(RetentionPolicy.RUNTIME)अपने एनोटेशन में भी जोड़ना चाहिए ।
डेविड नोवाक

9

या कह सकते हैं कि व्हाट्स फील्ड से पर्दा नहीं उठेगा:

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

अपनी कक्षा को विशेषता पर:

private **transient** boolean nameAttribute;

17
क्षणिक और स्थिर क्षेत्रों को डिफ़ॉल्ट रूप से बाहर रखा गया है; इसके लिए कॉल करने की कोई आवश्यकता नहीं excludeFieldsWithModifiers()है।
डेरेक जॉकी

9

मैंने इस रणनीति का उपयोग किया: मैंने हर उस क्षेत्र को छोड़ दिया, जो @SerializedName एनोटेशन के साथ चिह्नित नहीं है , अर्थात:

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

यह लौट आता है

{"विज़िबलवैल्यू": "मैं इसे देखूंगा"}


6

एक अन्य दृष्टिकोण (विशेष रूप से उपयोगी है यदि आपको रनटाइम के क्षेत्र को बाहर करने का निर्णय लेने की आवश्यकता है) अपने आगजनी उदाहरण के साथ एक टाइप एडेप्टर पंजीकृत करना है। नीचे उदाहरण:

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

नीचे दिए गए मामले में, सर्वर दो मूल्यों में से एक की उम्मीद करेगा, लेकिन जब से वे दोनों स्याही थे तब गेसन उन दोनों को अनुक्रमित करेगा। मेरा लक्ष्य सर्वर पर पोस्ट किए गए 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

कोटलिन का @Transientएनोटेशन भी स्पष्ट रूप से ट्रिक करता है।

data class Json(
    @field:SerializedName("serialized_field_1") val field1: String,
    @field:SerializedName("serialized_field_2") val field2: String,
    @Transient val field3: String
)

आउटपुट:

{"serialized_field_1":"VALUE1","serialized_field_2":"VALUE2"}

1

मैं केवल @Exposeएनोटेशन लगाकर काम कर रहा हूं , यहां मेरा संस्करण है जो मैं उपयोग करता हूं

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

में Modelवर्ग:

@Expose
int number;

public class AdapterRestApi {

में Adapterवर्ग:

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

1

मेरे पास कोटलिन संस्करण है

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
internal annotation class JsonSkip

class SkipFieldsStrategy : ExclusionStrategy {

    override fun shouldSkipClass(clazz: Class<*>): Boolean {
        return false
    }

    override fun shouldSkipField(f: FieldAttributes): Boolean {
        return f.getAnnotation(JsonSkip::class.java) != null
    }
}

और आप इसे रिट्रोफिट GSONConverterFactory में कैसे जोड़ सकते हैं:

val gson = GsonBuilder()
                .setExclusionStrategies(SkipFieldsStrategy())
                //.serializeNulls()
                //.setDateFormat(DateFormat.LONG)
                //.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
                //.setPrettyPrinting()
                //.registerTypeAdapter(Id.class, IdTypeAdapter())
                .create()
        return GsonConverterFactory.create(gson)

0

यह मैं हमेशा उपयोग करता हूं:

Gson में लागू डिफ़ॉल्ट व्यवहार यह है कि अशक्त ऑब्जेक्ट फ़ील्ड्स को अनदेखा कर दिया जाता है।

इसका मतलब है कि GSON ऑब्जेक्ट, JSON के लिए शून्य मान वाले फ़ील्ड को अनुक्रमित नहीं करता है। यदि जावा ऑब्जेक्ट में कोई फ़ील्ड शून्य है, तो Gson इसे बाहर कर देता है।

आप इस फ़ंक्शन का उपयोग किसी वस्तु को अपने आप से शून्य या अच्छी तरह से सेट करने के लिए कर सकते हैं

     /**
   * convert object to json
   */
  public String toJson(Object obj) {
    // Convert emtpy string and objects to null so we don't serialze them
    setEmtpyStringsAndObjectsToNull(obj);
    return gson.toJson(obj);
  }

  /**
   * Sets all empty strings and objects (all fields null) including sets to null.
   *
   * @param obj any object
   */
  public void setEmtpyStringsAndObjectsToNull(Object obj) {
    for (Field field : obj.getClass().getDeclaredFields()) {
      field.setAccessible(true);
      try {
        Object fieldObj = field.get(obj);
        if (fieldObj != null) {
          Class fieldType = field.getType();
          if (fieldType.isAssignableFrom(String.class)) {
            if(fieldObj.equals("")) {
              field.set(obj, null);
            }
          } else if (fieldType.isAssignableFrom(Set.class)) {
            for (Object item : (Set) fieldObj) {
              setEmtpyStringsAndObjectsToNull(item);
            }
            boolean setFielToNull = true;
            for (Object item : (Set) field.get(obj)) {
              if(item != null) {
                setFielToNull = false;
                break;
              }
            }
            if(setFielToNull) {
              setFieldToNull(obj, field);
            }
          } else if (!isPrimitiveOrWrapper(fieldType)) {
            setEmtpyStringsAndObjectsToNull(fieldObj);
            boolean setFielToNull = true;
            for (Field f : fieldObj.getClass().getDeclaredFields()) {
              f.setAccessible(true);
              if(f.get(fieldObj) != null) {
                setFielToNull = false;
                break;
              }
            }
            if(setFielToNull) {
              setFieldToNull(obj, field);
            }
          }
        }
      } catch (IllegalAccessException e) {
        System.err.println("Error while setting empty string or object to null: " + e.getMessage());
      }
    }
  }

  private void setFieldToNull(Object obj, Field field) throws IllegalAccessException {
    if(!Modifier.isFinal(field.getModifiers())) {
      field.set(obj, null);
    }
  }

  private boolean isPrimitiveOrWrapper(Class fieldType)  {
    return fieldType.isPrimitive()
        || fieldType.isAssignableFrom(Integer.class)
        || fieldType.isAssignableFrom(Boolean.class)
        || fieldType.isAssignableFrom(Byte.class)
        || fieldType.isAssignableFrom(Character.class)
        || fieldType.isAssignableFrom(Float.class)
        || fieldType.isAssignableFrom(Long.class)
        || fieldType.isAssignableFrom(Double.class)
        || fieldType.isAssignableFrom(Short.class);
  }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.