2011-02-13 27 views
39

मैं जैक्सन निम्नलिखित निर्माता के साथ एक वर्ग deserialize करना चाहते हैं:जैक्सन + बिल्डर पैटर्न?

public Clinic(String name, Address address) 

पहला तर्क deserializing आसान है। समस्या यह है कि पता के रूप में परिभाषित किया गया है है:

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

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

उत्तर

6

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

सबसे पहले आप अपने Address वर्ग को यह टिप्पणी जोड़ने के लिए की जरूरत है:

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

यदि आप इस दूसरे एनोटेशन को छोड़ सकते हैं:

@JsonDeserialize(builder = Address.Builder.class) 

तो फिर आप अपने Builder वर्ग को यह टिप्पणी जोड़ने के लिए की जरूरत है निर्माण के लिए अपने बिल्डर के निर्माण विधि का नाम बदलने में प्रसन्नता हो रही है, और सेट के बजाए आपके बिल्डर के सेटर्स को प्रीफ़िक्स किया जाना चाहिए।

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

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

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

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

कोडहॉस में अब जिरा उपलब्ध नहीं है लेकिन लिंक किए गए मुद्दे का वर्णन यहां किया गया है: http://wiki.fasterxml.com/JacksonFeatureBuilderPattern – Paul

+0

बिल्डर पैटर्न के लिए समर्थन लंबे समय से जैक्सन 2.2 की तरह कुछ जोड़ा गया है। – StaxMan

66

:

+0

अद्यतन के लिए धन्यवाद! – Gili

+8

यदि यह सभी को '@ JsonPOJOBuilder' एनोटेशन से छुटकारा पाने के लिए वांछित है, तो "बिल्ड" बनाने के लिए "बनाएं" का नाम बदलें और '@ जेसनप्रॉपर्टी' के साथ प्रत्येक बिल्डर सेटर्स को एनोटेट करें। –

+0

यह सुनहरा है। धन्यवाद। –

15

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

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

तो फिर तुम मानकों के रूप में नीचे व्याख्या करना चाहिए:

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

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

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

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

संबंधित मुद्दे