Java 杰克逊&x2B;建筑模式?
我希望Jackson使用以下构造函数反序列化类:Java 杰克逊&x2B;建筑模式?,java,json,jersey,jackson,Java,Json,Jersey,Jackson,我希望Jackson使用以下构造函数反序列化类: public Clinic(String name, Address address) 反序列化第一个参数很容易。问题在于地址的定义如下: public class Address { private Address(Map<LocationType, String> components) ... public static class Builder { public Builder setCity(Str
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();
}
}
公共类地址{
专用地址(映射组件)
...
公共静态类生成器{
公共生成器设置城市(字符串值);
公共生成器设置国家(字符串值);
公共广播创建();
}
}
并且是这样构造的:newaddress.Builder().setCity(“foo”).setCountry(“bar”).create()代码>
有没有办法从Jackson那里获取键值对,以便自己构造地址?或者,有没有办法让Jackson使用Builder类本身呢?目前还没有对Builder模式的支持,尽管它在很久以前就被请求过(最终提交了Jira问题)——如果有足够的需求,它可能会被添加到1.8版本中(请确保在Jira上投票!)。这是一个合理的附加功能,只是延迟了开发人员的时间。但我认为这将是一个很好的补充。我最终使用@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();
}
}
@JsonDeserialize(使用=JacksonDeserializer.class)
公共课堂演讲
{...}
@JsonCachable
静态类JacksonDeserializer扩展了JsonDeserializer
{
@凌驾
公共地址反序列化(JsonParser解析器,反序列化上下文)
抛出IOException、JsonProcessingException
{
JsonToken token=parser.getCurrentToken();
if(令牌!=JsonToken.START\u对象)
{
抛出新的JsonMappingException(“预期的START_对象:+token,parser.getCurrentLocation());
}
token=parser.nextToken();
生成器结果=新生成器();
while(令牌!=JsonToken.END\u对象)
{
if(令牌!=JsonToken.FIELD\u NAME)
{
抛出新的JsonMappingException(“预期的字段名称:+token,parser.getCurrentLocation());
}
LocationType key=LocationType.valueOf(parser.getText());
token=parser.nextToken();
if(令牌!=JsonToken.VALUE\u字符串)
{
抛出新的JsonMappingException(“预期值\字符串:+token,parser.getCurrentLocation());
}
字符串值=parser.getText();
//我们的生成器允许传递键值对
//除了正常的setter方法之外。
结果。输入(键、值);
token=parser.nextToken();
}
返回result.create();
}
}
只要您使用的是Jackson 2+,现在就有了
首先,您需要将此注释添加到地址
类:
@JsonDeserialize(builder = Address.Builder.class)
然后,您需要将此注释添加到Builder
类:
@JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")
如果愿意将生成器的create方法重命名为build,将生成器的setter前缀改为with,而不是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();
}
}
@JsonDeserialize(builder=Address.builder.class)
公共课堂演讲
{
专用地址(映射组件)
...
@JsonPOJOBuilder(buildMethodName=“create”,withPrefix=“set”)
公共静态类生成器
{
公共生成器设置城市(字符串值);
公共生成器设置国家(字符串值);
公共广播创建();
}
}
来自@Rupert Madden Abbott的答案很有效。但是,如果您有一个非默认构造函数,例如
Builder(String city, String country) {...}
然后,您应按如下所示对参数进行注释:
@JsonCreator
Builder(@JsonProperty("city") String city,
@JsonProperty("country") String country) {...}
在本例中,一个适合我的解决方案(我使用了“Lombok”生成器注释)
我希望这对你也有用。这对我有用:@noargsconstuctor
这样做的唯一缺点是可以再次使用do=new ADTO()。
但是,嘿,我无论如何都不喜欢反编码警察,告诉我如何使用别人的代码:-)
所以,按你喜欢的方式使用我的POJO DTOS。有或没有建设者。我建议:和建筑商一起做,但做我的客人
@Data
@Builder
//Dont forget this! Otherwise no Jackson serialisation possible!
@NoArgsConstructor
@AllArgsConstructor
public class ADTO {
.....
}
如果希望同时删除@JsonPOJOBuilder
注释,请将“create”重命名为“build”,并使用@JsonProperty
注释每个生成器设置器。这是金色的。谢谢。这已经过时了,在Lombok 1.18.4中,您可以使用@Jacksonized
,它将内部生成器和jackson注释替换为单个thing@Randakar我不认为这是过时的,因为a)@Jackonized
是Lombok中刚刚发布的实验特性。我认为不必要地鼓励采用实验特性不是一个好主意。b) 这个问题没有提到或使用龙目山。我认为不必要地引入依赖性来解决问题不是一个好主意。这很公平。我用这些信息更新了另一个与lombok相关的答案,显然我的网络太宽了。Codehaus不再提供Jira,但这里描述了相关的问题:很久以前就添加了对构建器模式的支持,类似于Jackson 2.2。这可能是您最终实现它的方式,但这个答案实际上并没有回答所提出的问题。@Rupert Madden Abbott发布的答案应标记为已接受的答案。这已过时,在Lombok 1.18.4中,您可以使用@Jacksonized
,它用一个东西替换内部生成器和jackson注释
@Data
@Builder
//Dont forget this! Otherwise no Jackson serialisation possible!
@NoArgsConstructor
@AllArgsConstructor
public class ADTO {
.....
}