Java 传递到Jersey+;时从实体中删除字段;杰克逊

Java 传递到Jersey+;时从实体中删除字段;杰克逊,java,json,jersey,jackson,dropwizard,Java,Json,Jersey,Jackson,Dropwizard,我正在使用Jersey+Jackson(内置Dropwizard)创建一系列web服务。我通过将对象传递给Jersey中的响应对象,直接映射Json中的对象: myObject object = new myObject(fields...); return Response.ok(object).build(); 字段在myObject类中使用JsonProperty(“fieldName”)正确注释 但是,如果我有一个字段需要存储到数据库(例如:密码散列),但我不想传入请求响应,那么在将实

我正在使用Jersey+Jackson(内置Dropwizard)创建一系列web服务。我通过将对象传递给Jersey中的响应对象,直接映射Json中的对象:

myObject object = new myObject(fields...);
return Response.ok(object).build();
字段在myObject类中使用JsonProperty(“fieldName”)正确注释

但是,如果我有一个字段需要存储到数据库(例如:密码散列),但我不想传入请求响应,那么在将实体传递到响应对象时如何删除该字段


我不能用JsonIgnore对字段进行注释,否则当我将Json映射到数据库(ElasticSearch)时,该字段将不会被序列化。

一个选项是简单地将字段设置为
null
。要将
ObjectMapper
配置为在字段为null时完全忽略JSON中的字段,只需执行以下操作

@Override
public void run(YourConfiguration configuration,
        Environment environment) throws Exception {
    ...
    environment.getObjectMapper().setSerializationInclusion(Include.NON_NULL);
}
另一方面,这种安全性是使用DTO(数据传输对象)的原因之一,DTO是一个额外的实体“视图”层,它将我们发送的表示与持久性层(db实体对象)分离。创建另一个具有相同/相似属性的对象似乎是多余的,但安全填充是值得的


另外,虽然还不是正式发布,但它使用了Jersey 2,它允许我们过滤掉我们不想发送的数据,而无需创建DTO。我只是想提一下。

您应该同时使用JsonIgnore和JsonProperty来实现这一点

  public class User {

  private String name;
  private String password;

  @JsonProperty    
  public void setPassword(String password) {
    this.password = password;
  }

  @JsonIgnore
  public String getPassword() {
    return this.password;
  }

}

@setter方法上的JsonProperty将用于序列化,getter方法上的JsonIgnore将用于反序列化

实际上@Manikandan的答案应该适合你。看

在最坏的情况下,您可以尝试实现JsonSerializer

public class MyObjectSerializer extends JsonSerializer<MyObject> {

    @Override
    public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        jgen.writeStartObject();
        jgen.writeString(value.getField1());
        jgen.writeString(value.getField2());
        /* and not include field that you don't want to serialize */
        jgen.writeEndObject();
    }

}

@JsonSerialize(using = MyObjectSerializer.class)
public class MyObject {

    String field1;
    Integer field2;
    String fieldNotToBeSerialized;

    public String getField1() {
        return field1;
    }
    public void setField1(String field1) {
        this.field1 = field1;
    }
    public Integer getField2() {
        return field2;
    }
    public void setField2(Integer field2) {
        this.field2 = field2;
    }
    public String getFieldNotToBeSerialized() {
        return fieldNotToBeSerialized;
    }
    public void setFieldNotToBeSerialized(String fieldNotToBeSerialized) {
        this.fieldNotToBeSerialized = fieldNotToBeSerialized;
    }

}
公共类MyObjectSerializer扩展JsonSerializer{
@凌驾
public void serialize(MyObject值、JsonGenerator jgen、SerializerProvider提供程序)引发IOException、JsonProcessingException{
jgen.writeStartObject();
writeString(value.getField1());
writeString(value.getField2());
/*并且不包括您不想序列化的字段*/
jgen.writeEndObject();
}
}
@JsonSerialize(使用=MyObjectSerializer.class)
公共类MyObject{
字符串字段1;
整型字段2;
字符串字段不进行序列化;
公共字符串getField1(){
返回字段1;
}
公共无效集合字段1(字符串字段1){
此字段1=字段1;
}
公共整数getField2(){
返回字段2;
}
公共无效集合字段2(整数字段2){
this.field2=field2;
}
公共字符串getFieldNotToBeSerialized(){
返回字段不进行序列化;
}
public void setFieldNotToBeSerialized(字符串字段nottobeserialized){
this.fieldNotToBeSerialized=fieldNotToBeSerialized;
}
}

谢谢,但在这种情况下,即使在应用程序的“内部”,我也不会得到密码字段;我需要它在登录时验证用户。你说的“在”应用程序内部是什么意思。您可以直接在应用程序内使用对象。它将具有密码值。我将对象直接存储在JS上。如果我添加JsonIgnore来获得;当我将对象映射到JSON时,更新时会丢失密码字段;我从未使用过实体过滤,但我认为这是实现我所需要的最好方法。能否提供Dropwizard中实体筛选的示例(我使用的是DW 0.8.0-rc1)?实体筛选是否可能只在单个资源/路由上工作,而不在全局应用程序级别工作?我刚刚意识到它目前不支持Jackson。我一直在研究如何实现一些东西,但这绝非小事。我的意思是使用DTO或将其设置为null。如果您想要一个更优雅的解决方案(不必在resource方法中将字段设置为null),可以使用JAX-RS拦截器,但在这样做之前我会三思。一些安全的东西,比如密码,我会让它尽可能远离最终进程