जैक्सन ने 'हटा' से आदिम बुलियन क्षेत्र का नाम बदला


97

यह एक डुप्लिकेट हो सकता है। लेकिन मुझे अपनी समस्या का हल नहीं मिल रहा है।

मुझे कक्षा में जाना है

public class MyResponse implements Serializable {

    private boolean isSuccess;

    public boolean isSuccess() {
        return isSuccess;
    }

    public void setSuccess(boolean isSuccess) {
        this.isSuccess = isSuccess;
    }
}

ग्रहण करने वालों और बसने वालों को ग्रहण द्वारा उत्पन्न किया जाता है।

दूसरे वर्ग में, मैंने मान को सही पर सेट किया, और इसे JSON स्ट्रिंग के रूप में लिखा।

System.out.println(new ObjectMapper().writeValueAsString(myResponse));

JSON में, कुंजी के रूप में आ रहा है {"success": true}

मुझे isSuccessखुद की चाभी चाहिए । क्या जैक्सन क्रमांकन करते समय सेटर विधि का उपयोग कर रहा है? फ़ील्ड का नाम कैसे बनाया जाए?


1
अगर आपकी प्रॉपर्टी का नाम है isSuccessतो आपको isIsSuccessलगता है कि मेरे नाम की विधि होनी चाहिए
जेन्स

मै समझता हुँ। मैंने सोचा कि यह बेहतर है SetSuccess क्योंकि यह ग्रहण द्वारा उत्पन्न हुआ है। (एक मानक के बाद)
iCode

जवाबों:


121

यह थोड़ा देर से जवाब है, लेकिन इस पृष्ठ पर आने वाले किसी अन्य व्यक्ति के लिए उपयोगी हो सकता है।

जैक्सन का नाम बदलने के लिए जैक्सन का उपयोग करने के लिए नाम बदलने का एक सरल समाधान @JsonProperty एनोटेशन का उपयोग करना है , इसलिए आपका उदाहरण बन जाएगा:

public class MyResponse implements Serializable {

    private boolean isSuccess;

    @JsonProperty(value="isSuccess")        
    public boolean isSuccess() {
        return isSuccess;
    }

    public void setSuccess(boolean isSuccess) {
        this.isSuccess = isSuccess;
    }
}

फिर इसे JSON के रूप में क्रमबद्ध किया जाएगा {"isSuccess":true}, लेकिन आपके गेटटर विधि के नाम को संशोधित नहीं करने का लाभ होगा।

ध्यान दें कि इस मामले में आप एनोटेशन भी लिख सकते हैं @JsonProperty("isSuccess")क्योंकि इसमें केवल एक ही valueतत्व है


यह विधि मेरे मामले के लिए काम नहीं करेगी क्योंकि वर्ग मेरे पास नहीं है क्योंकि यह 3 पार्टी निर्भरता से आता है। ऐसे मामले के लिए, नीचे मेरा जवाब देखें।
एडमंडप्टी

5
Im जैकसन के साथ स्प्रिंग बूट का उपयोग कर रहा है, लेकिन दो फ़ील्ड एक "सफलता" है और अन्य "isSuccess" है और जब मैं केवल एक फ़ील्ड "की तुलना में गैर आदिम बुलियन का उपयोग करता हूँ"
विशाल सिंगला

@VishalSingla मेरे पास एक ही सटीक मुद्दा है, यह समाधान स्प्रिंग बूट में दो क्षेत्रों का उत्पादन करता है
एरॉन फीचर

GSON के साथ क्रमबद्धता ठीक काम करती है।
नईम

23

मैं हाल ही में इस मुद्दे पर भाग गया और यही मुझे मिला। जैक्सन किसी भी वर्ग का निरीक्षण करेंगे जो आप इसे पाने वालों और बसने वालों के लिए पास करते हैं, और उन तरीकों का उपयोग करते हैं जो क्रमबद्धता और deserialization के लिए करते हैं। उन विधियों में "get", "is" और "set" का उपयोग JSON फ़ील्ड ("getVsValid" और "IVVValid "के लिए कुंजी के रूप में किया जाएगा)।

public class JacksonExample {   

    private boolean isValid = false;

    public boolean getIsValid() {
        return isValid;
    }

    public void setIsValid(boolean isValid) {
        this.isValid = isValid;
    }
} 

इसी तरह "असफल" "सफल" हो जाएगा, जब तक कि इसका नाम बदलकर "isIsSuccess" या "getIsSuccess" न बना दिया जाए

यहां पढ़ें: http://www.citrine.io/blog/2015/5/20/jackson-json-processor


6
जावा में बूलियन डेटा प्रकार के लिए isValid सही नामकरण सम्मेलन नहीं है। वैध होना चाहिए और isValid (), setValid ()
vels4j

2
लेकिन क्या ऐसा बिल्कुल नहीं माना जाता है? एक सम्मेलन? यदि यह मौजूद है, तो क्या आप जैक्सन संदर्भ से लिंक कर सकते हैं जो कहता है कि यह JSON फ़ील्ड्स के रूप में गेट्टर नामों का उपयोग करता है? या आपको लगता है कि यह एक खराब डिजाइन विकल्प है?
अभिनव विष्ट

2
काश इसके लिए चेतावनी होती
RyPope

जब आप अत्यधिक विशिष्ट कार्यान्वयन के साथ काम कर रहे हों तो @ vel44j नामकरण परंपराएँ खिड़की से बाहर चली जाती हैं।
ड्रैगस

13

नीचे दिए गए दोनों एनोटेशन का उपयोग करके आउटपुट JSON को शामिल करने के लिए मजबूर करता है is_xxx:

@get:JsonProperty("is_something")
@param:JsonProperty("is_something")

यह इस सवाल का सबसे अच्छा जवाब है।
डस्टीवन

2
क्या वह जावा है? शायद यह कोटलीन है?
धब्बेदार

7

आप ObjectMapperनिम्नानुसार अपने कॉन्फ़िगर कर सकते हैं:

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
            @Override
            public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
            {
                if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class)
                        && method.getName().startsWith("is")) {
                    return method.getName();
                }
                return super.nameForGetterMethod(config, method, defaultName);
            }
        });

1
मुझे पसंद है कि आप इसे कॉन्फ़िगरेशन के माध्यम से हल करने का प्रयास कर रहे हैं। हालाँकि, यह केवल तभी काम करेगा जब आप हमेशा अपने बूलियन फ़ील्ड्स और JSON गुणों को "is" के साथ जोड़ते हैं। मान लें कि आपके पास एक और बूलियन फ़ील्ड है जिसे "सक्षम" नाम दिया गया है जिसे आप इस तरह से क्रमबद्ध करना चाहते हैं। क्योंकि जेनरेट की गई विधि "EEnabled ()" है, उपरोक्त कोड तब इसे केवल "सक्षम" के बजाय "EEnabled" में अनुक्रमित करेगा। अंततः, समस्या यह है कि दोनों क्षेत्रों "x" और "isX" के लिए, ग्रहण विधि "isX ()" उत्पन्न करती है; इसलिए आप फ़ील्ड से मेल खाते प्रॉपर्टी नाम का अनुमान नहीं लगा सकते।
डेविड सिएगल

@DavidSiegal आधार पर बुरक जवाब मैंने ऐसे मामले का समर्थन करने के लिए नीचे दिए गए उत्तर को बढ़ाया है।
एडमंडप्यू

5

जब आप कोटलिन और डेटा वर्गों का उपयोग कर रहे हैं:

data class Dto(
    @get:JsonProperty("isSuccess") val isSuccess: Boolean
)

@param:JsonProperty("isSuccess")यदि आप JSON को डिस्अरीलाइज़ करने जा रहे हैं तो आपको इसे जोड़ना पड़ सकता है ।


2

उत्कर्ष के उत्तर पर निर्माण ।।

गेट्स नाम माइनस मिलता है / इसे JSON नाम के रूप में उपयोग किया जाता है।

public class Example{
    private String radcliffe; 

    public getHarryPotter(){
        return radcliffe; 
    }
}

को {"harryPotter" के रूप में संग्रहीत किया जाता है : "जो भी हो YouGaveHere"}


Deserialization के लिए, जैक्सन सेटर और फ़ील्ड नाम दोनों के खिलाफ जाँच करता है। Json स्ट्रिंग {"word1": "उदाहरण"} के लिए , नीचे दोनों मान्य हैं।

public class Example{
    private String word1; 

    public setword2( String pqr){
        this.word1 = pqr; 
    }
}

public class Example2{
    private String word2; 

    public setWord1(String pqr){
        this.word2 = pqr ; 
    }
}

एक और दिलचस्प सवाल यह है कि जैक्सन deserialization के लिए किस क्रम पर विचार करता है। अगर मैं {"word1": "myName"} के साथ डिसर्बिज करने की कोशिश करता हूं

public class Example3{
    private String word1;
    private String word2; 

    public setWord1( String parameter){
        this.word2 = parameter ; 
    }
}

मैंने उपरोक्त मामले का परीक्षण नहीं किया है, लेकिन शब्द 1 और शब्द 2 के मूल्यों को देखना दिलचस्प होगा ...

नोट: मैंने इस बात पर जोर देने के लिए बहुत अलग-अलग नामों का इस्तेमाल किया कि किन क्षेत्रों में समान होने की आवश्यकता है।


2

मैं कुछ कस्टम नामकरण रणनीतियों के साथ गड़बड़ नहीं करना चाहता था, न ही कुछ एक्सेसरों को फिर से बनाना।
कम कोड, मैं सबसे ज्यादा खुश हूं।

यह हमारे लिए चाल थी:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonIgnoreProperties({"success", "deleted"}) // <- Prevents serialization duplicates 
public class MyResponse {

    private String id;
    private @JsonProperty("isSuccess") boolean isSuccess; // <- Forces field name
    private @JsonProperty("isDeleted") boolean isDeleted;

}

1

इस समस्या के लिए एक और तरीका है।

बस एक नए उप-वर्ग को परिभाषित करें PropertyNamingStrategy का विस्तार और ObjectMapper उदाहरण के लिए इसे पास करें।

यहाँ एक कोड स्निपेट अधिक मदद हो सकती है:

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
        @Override
        public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
            String input = defaultName;
            if(method.getName().startsWith("is")){
                input = method.getName();
            }

            //copy from LowerCaseWithUnderscoresStrategy
            if (input == null) return input; // garbage in, garbage out
            int length = input.length();
            StringBuilder result = new StringBuilder(length * 2);
            int resultLength = 0;
            boolean wasPrevTranslated = false;
            for (int i = 0; i < length; i++)
            {
                char c = input.charAt(i);
                if (i > 0 || c != '_') // skip first starting underscore
                {
                    if (Character.isUpperCase(c))
                    {
                        if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_')
                        {
                            result.append('_');
                            resultLength++;
                        }
                        c = Character.toLowerCase(c);
                        wasPrevTranslated = true;
                    }
                    else
                    {
                        wasPrevTranslated = false;
                    }
                    result.append(c);
                    resultLength++;
                }
            }
            return resultLength > 0 ? result.toString() : input;
        }
    });

1

स्वीकृत उत्तर मेरे मामले के लिए काम नहीं करेगा।

मेरे मामले में, वर्ग मेरे स्वामित्व में नहीं है। समस्याग्रस्त वर्ग 3 पार्टी निर्भरताओं से आता है, इसलिए मैं इसमें केवल @JsonPropertyएनोटेशन नहीं जोड़ सकता।

इसे हल करने के लिए, ऊपर दिए गए @burak उत्तर से प्रेरित होकर, मैंने PropertyNamingStrategyनिम्नलिखित के रूप में एक कस्टम बनाया :

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
  @Override
  public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
  {
    if (method.getParameterCount() == 1 &&
            (method.getRawParameterType(0) == Boolean.class || method.getRawParameterType(0) == boolean.class) &&
            method.getName().startsWith("set")) {

      Class<?> containingClass = method.getDeclaringClass();
      String potentialFieldName = "is" + method.getName().substring(3);

      try {
        containingClass.getDeclaredField(potentialFieldName);
        return potentialFieldName;
      } catch (NoSuchFieldException e) {
        // do nothing and fall through
      }
    }

    return super.nameForSetterMethod(config, method, defaultName);
  }

  @Override
  public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
  {
    if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class)
        && method.getName().startsWith("is")) {

      Class<?> containingClass = method.getDeclaringClass();
      String potentialFieldName = method.getName();

      try {
        containingClass.getDeclaredField(potentialFieldName);
        return potentialFieldName;
      } catch (NoSuchFieldException e) {
        // do nothing and fall through
      }
    }
    return super.nameForGetterMethod(config, method, defaultName);
  }
});

मूल रूप से यह क्या करता है serializing और deserializing, यह लक्ष्य / स्रोत वर्ग जो संपत्ति नाम वर्ग में मौजूद है, चाहे वह है में चेक से पहले, है isEnabledया enabledसंपत्ति।

उसके आधार पर, मैपर अनुक्रमित होगा और मौजूद संपत्ति के नाम को डिसेर्बलाइज करेगा।


0

आप आदिम बूलियन को java.lang.Boolean (+ उपयोग @JsonPropery) में बदल सकते हैं

@JsonProperty("isA")
private Boolean isA = false;

public Boolean getA() {
    return this.isA;
}

public void setA(Boolean a) {
    this.isA = a;
}

मेरे लिए उत्कृष्ट काम किया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.