2011-02-13 92 views
39

我想傑克遜反序列化類下面的構造:Jackson + Builder模式?

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

有沒有一種辦法,以構建自己的地址從傑克遜獲得鍵值對?或者,有沒有辦法讓Jackson使用Builder類本身?

回答

6

我結束了實施這一使用@JsonDeserialize如下:只要你使用的是傑克遜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(); 
    } 
} 
2

目前尚不支持構建器模式,雖然它已被要求相當一段時間(最終Jira問題http://jira.codehaus.org/browse/JACKSON-469已提交) - 如果有足夠的需求,它可以添加到1.8版本中一定要在Jira投票!)。這是一個合理的附加功能,只會延誤開發人員的時間。但我認爲這將是很好的補充。

+1

Codehaus不再有Jira可用,但鏈接的問題在這裏描述:http://wiki.fasterxml.com/JacksonFeatureBuilderPattern – Paul 2016-02-26 14:10:06

+0

支持Builder模式已經很久以來,像傑克遜2.2一樣。 – StaxMan 2016-03-16 05:17:33

66

首先,你需要這個註釋添加到您的Address類:

@JsonDeserialize(builder = Address.Builder.class) 

然後,你需要這個註釋添加到您的Builder類:

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

,如果你可以跳過第二個註解很樂意重新命名你的Builder的create方法來構建,而你的Builder的setter將被設置爲前綴而不是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(); 
    } 
} 
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 
) 

我希望對你也有用。