जैक्सन + बिल्डर पैटर्न?


89

मैं चाहूंगा कि जैक्सन निम्नलिखित कंस्ट्रक्टर के साथ एक वर्ग को अलग कर दे:

public Clinic(String name, Address address)

पहले तर्क का वर्णन करना आसान है। समस्या यह है कि पते को इस प्रकार परिभाषित किया गया है:

public class Address {
  private Address(Map<LocationType, String> components)
  ...

  public static class Builder {
    public Builder setCity(String value);
    public Builder setCountry(String value);
    public Address create();
  }
}

और इस तरह बनाया गया है: new Address.Builder().setCity("foo").setCountry("bar").create();

क्या पता स्वयं बनाने के लिए जैक्सन से कुंजी-मूल्य जोड़े प्राप्त करने का कोई तरीका है? वैकल्पिक रूप से, क्या जैक्सन को बिल्डर वर्ग का उपयोग करने का एक तरीका है?

जवाबों:


139

जब तक आप जैक्सन 2+ का उपयोग कर रहे हैं, तब तक इसके लिए समर्थन में बनाया गया है

सबसे पहले आपको अपनी Addressकक्षा में यह एनोटेशन जोड़ने की आवश्यकता है :

@JsonDeserialize(builder = Address.Builder.class)

फिर आपको अपनी Builderकक्षा में यह एनोटेशन जोड़ने की आवश्यकता है :

@JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")

यदि आप अपने बिल्डर की बनाने की विधि का नाम बदलने के लिए खुश हैं, और अपने बिल्डर के सेटर्स को सेट के बजाय, के साथ उपसर्ग किए जाने पर आप इस दूसरी एनोटेशन को छोड़ सकते हैं।

पूर्ण उदाहरण:

@JsonDeserialize(builder = Address.Builder.class)
public class Address
{
  private Address(Map<LocationType, String> components)
  ...

  @JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")
  public static class Builder
  {
    public Builder setCity(String value);
    public Builder setCountry(String value);
    public Address create();
  }
}

14
यदि यह @JsonPOJOBuilderएनोटेशन से सभी को एक साथ निकालने के लिए वांछित है , तो "बनाएँ" का नाम बदलकर "बिल्ड" करें और प्रत्येक बिल्डर के साथ एनोटेट करें @JsonProperty
सैम बेरी

यह सुनहरा है। धन्यवाद।
मुकुल गोयल

यह अब पुराना है, लोम्बोक 1.18.4 के साथ आप उपयोग कर सकते हैं @Jacksonizedजो आंतरिक बिल्डर और
जैकसन

@ रांडकार मुझे नहीं लगता कि यह पुराना है क्योंकि a) लोम्बोक @Jackonized में एक अभी जारी प्रायोगिक विशेषता है। मुझे नहीं लगता कि प्रयोगात्मक सुविधाओं को अपनाने के लिए अनावश्यक रूप से प्रोत्साहित करना एक अच्छा विचार है। ख) इस सवाल में लंबोक का उल्लेख या उपयोग नहीं है। मुझे नहीं लगता कि किसी समस्या को हल करने के लिए अनावश्यक रूप से निर्भरता का परिचय देना एक अच्छा विचार है।
रूपर्ट मैडेन-एबट

19

@ रिपर्ट मैडेन-एबट से जवाब काम करता है। हालाँकि, यदि आपके पास एक गैर-डिफ़ॉल्ट निर्माता है, जैसे,

Builder(String city, String country) {...}

फिर आपको नीचे दिए गए मापदंडों की व्याख्या करनी चाहिए:

@JsonCreator
Builder(@JsonProperty("city")    String city, 
        @JsonProperty("country") String country) {...}

9

एक समाधान जो इस मामले में मेरे लिए उपयुक्त था (मैंने "लोम्बोक" बिल्डर एनोटेशन का इस्तेमाल किया)।

@Getter
@Builder(builderMethodName = "builder")
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@JsonAutoDetect(
    fieldVisibility = JsonAutoDetect.Visibility.ANY,
    creatorVisibility = JsonAutoDetect.Visibility.ANY
)

मुझे आशा है कि आप यू के लिए भी उपयोगी होंगे।


यह अब पुराना हो गया है, लोम्बोक 1.18.4 के साथ आप उपयोग कर सकते हैं @Jacksonizedजो आंतरिक बिल्डर और
जैकसन

7

मैंने @JsonDeserialize का उपयोग करके इसे इस प्रकार लागू किया:

@JsonDeserialize(using = JacksonDeserializer.class)
public class Address
{...}

@JsonCachable
static class JacksonDeserializer extends JsonDeserializer<Address>
{
    @Override
    public Address deserialize(JsonParser parser, DeserializationContext context)
        throws IOException, JsonProcessingException
    {
        JsonToken token = parser.getCurrentToken();
        if (token != JsonToken.START_OBJECT)
        {
            throw new JsonMappingException("Expected START_OBJECT: " + token, parser.getCurrentLocation());
        }
        token = parser.nextToken();
        Builder result = new Builder();
        while (token != JsonToken.END_OBJECT)
        {
            if (token != JsonToken.FIELD_NAME)
            {
                throw new JsonMappingException("Expected FIELD_NAME: " + token, parser.getCurrentLocation());
            }
            LocationType key = LocationType.valueOf(parser.getText());

            token = parser.nextToken();
            if (token != JsonToken.VALUE_STRING)
            {
                throw new JsonMappingException("Expected VALUE_STRING: " + token, parser.getCurrentLocation());
            }
            String value = parser.getText();

            // Our Builder allows passing key-value pairs
            // alongside the normal setter methods.
            result.put(key, value);
            token = parser.nextToken();
        }
        return result.create();
    }
}

यह हो सकता है कि आपने इसे लागू करना कैसे समाप्त कर दिया, लेकिन यह उत्तर वास्तव में प्रश्न का उत्तर नहीं देता है। @ रिपर्ट मैडेन-एबट द्वारा पोस्ट किए गए उत्तर को स्वीकृत के रूप में चिह्नित किया जाना चाहिए।
kelnos

2

बिल्डर पैटर्न के लिए वर्तमान में कोई समर्थन नहीं है, हालांकि यह काफी समय पहले अनुरोध किया गया है (और अंत में जीरा मुद्दा http://jira.codehaus.org/browse/JACKSON-469 दायर किया गया था) - यह कुछ ऐसा है जिसे जोड़ा जा सकता है 1.8 रिलीज के लिए अगर पर्याप्त मांग है (जीरा में मतदान करना सुनिश्चित करें!)। यह एक उचित अतिरिक्त सुविधा है, और केवल समय डेवलपर्स की मात्रा में देरी है। लेकिन मुझे लगता है कि यह बहुत अच्छा होगा।


2
Codehaus के पास अब जीरा उपलब्ध नहीं है लेकिन जुड़ा हुआ मुद्दा यहां वर्णित है: wiki.fasterxml.com/JacksonFeatureBuilderPattern
पॉल

जैक्सन 2.2 जैसी चीज पर बिल्डर पैटर्न के लिए समर्थन लंबे समय से जोड़ा गया है।
स्टैक्मैन मैन 16'16

2

यह मेरे लिए काम कर रहा है: @NoArgsConstructor इसका एकमात्र दोष यह है कि कोई फिर से नया ADTO () कर सकता है। लेकिन, हे, मुझे किसी भी तरह डे कोड पुलिस पसंद नहीं है, मुझे किसी को कोड कोड का उपयोग करने का तरीका बताया गया है :-) इसलिए, मेरे POJO DTOS का उपयोग उस तरह से करें जैसे आप इसे पसंद करते हैं। बिल्डर के साथ या बिना। मेरा सुझाव है: एक बिल्डर के साथ करो, लेकिन मेरे मेहमान बनो ...

@Data
@Builder
//Dont forget this! Otherwise no Jackson serialisation possible!
@NoArgsConstructor
@AllArgsConstructor
public class ADTO {
.....
}

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