Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 杰克逊&x2B;建筑模式?_Java_Json_Jersey_Jackson - Fatal编程技术网

Java 杰克逊&x2B;建筑模式?

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

我希望Jackson使用以下构造函数反序列化类:

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 {
.....
}