传递给 Jersey + Jackson 时从实体中删除一个字段
Remove a field from entity when passing to Jersey + Jackson
我正在使用 Jersey + Jackson(内置于 Dropwizard)来创建一系列网络服务。我通过将对象传递给 Jersey 中的 Response 对象来直接映射 Json 中的对象:
myObject object = new myObject(fields...);
return Response.ok(object).build();
myObject class 中的字段已使用 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(数据传输对象)的原因之一,一个额外的实体 "view" 层将我们发送的表示与持久层(db 实体对象)分开).使用 same/similar 属性创建另一个对象似乎是多余的,但安全填充是值得的。
此外,虽然还不是正式版本,Dropwizard 0.8.0 uses Jersey 2, which introduced Entity Filtering 允许我们过滤掉不想发送的数据,而无需创建 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;
}
}
@JsonProperty on setter 方法将用于序列化,JsonIgnore on getter 方法将用于反序列化。
实际上@Manikandan 的回答应该适合您。参见 Only using @JsonIgnore during serialization, but not deserialization
在最坏的情况下,您可能会尝试实现 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;
}
}
我正在使用 Jersey + Jackson(内置于 Dropwizard)来创建一系列网络服务。我通过将对象传递给 Jersey 中的 Response 对象来直接映射 Json 中的对象:
myObject object = new myObject(fields...);
return Response.ok(object).build();
myObject class 中的字段已使用 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(数据传输对象)的原因之一,一个额外的实体 "view" 层将我们发送的表示与持久层(db 实体对象)分开).使用 same/similar 属性创建另一个对象似乎是多余的,但安全填充是值得的。
此外,虽然还不是正式版本,Dropwizard 0.8.0 uses Jersey 2, which introduced Entity Filtering 允许我们过滤掉不想发送的数据,而无需创建 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;
}
}
@JsonProperty on setter 方法将用于序列化,JsonIgnore on getter 方法将用于反序列化。
实际上@Manikandan 的回答应该适合您。参见 Only using @JsonIgnore during serialization, but not deserialization
在最坏的情况下,您可能会尝试实现 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;
}
}