Jackson 2:仅在序列化时忽略瞬态场
Jackson 2: Ignore transient field only when serialising
我在 JAX-RS 应用程序中使用 Jackson v2,我正在尝试弄清楚它是否可行
配置 "ObjectMapper" 以使用 transient 修饰符删除字段,但仅在序列化期间。
这是一个 DTO 来说明我的用例(省略了 getter 和 setter)
public class User {
private String email;
private transient String password;
}
考虑到上述 DTO,我希望有一个对象映射器可以删除
序列化时的密码字段,并在反序列化期间包含它。
关于瞬变,我唯一能找到的是:
MapperFeature.PROPAGATE_TRANSIENT_MARKER
但是那个配置与我的要求不相关。
P.S - 不使用注释,因为 DTO 不与任何库耦合,另外
我不一定能控制它们。
不知道,看起来 transient
属性修饰符加上 PROPAGATE_TRANSIENT_MARKER
就可以了。反序列化很简单。不过,在序列化期间有一些 fuss with the transient marker。您需要为字段提供吸气剂,否则您将陷入异常 "Unrecognized field ... not marked as ignorable".
为了满足额外的要求,我添加了一个使用 jackson mixins 的版本。请注意,mixin 版本会生成带有空密码字段的 json,而 PROPAGATE_TRANSIENT_MARKER 版本根本不会生成任何字段。
PROPAGATE_TRANSIENT_MARKER版本
public class SerializeDeserializeAttributes {
private final ObjectMapper mapper = new ObjectMapper();
public <T> T fromJson(String json, Class<T> c) throws IOException {
synchronized (mapper) {
mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, false);
return mapper.readValue(json, c);
}
}
public String toJson(Object o) throws JsonProcessingException {
synchronized (mapper) {
mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);
return mapper.writeValueAsString(o);
}
}
private static final String jsonFull = "{\"name\":\"A\",\"email\":\"a@a\",\"password\":\"a\",\"width\":1,\"height\":1}";
private static final String jsonPartial = "{\"name\":\"A\",\"email\":\"a@a\",\"width\":1,\"height\":1}";
private static final User user = new User("A", "a@a", "a", 1, 1);
@Test
public void serializeDeserialize() throws IOException {
assertEquals(user, fromJson(jsonFull, User.class));
assertEquals(jsonPartial, toJson(user));
assertEquals(user, fromJson(jsonFull, User.class));
assertEquals(jsonPartial, toJson(user));
}
}
Mixin版本
public class SerializeDeserializeAttributesMixin {
public abstract class UserMixin {
@JsonSerialize(using = PwdSerializer.class)
transient String password;
}
static class PwdSerializer extends StdSerializer<String> {
public PwdSerializer() {
this(String.class);
}
private PwdSerializer(Class<String> t) {
super(t);
}
@Override
public void serialize(String s, JsonGenerator jg, SerializerProvider sp) throws IOException {
jg.writeString("");
}
}
private static final String jsonFull = "{\"name\":\"A\",\"email\":\"a@a\",\"password\":\"a\",\"width\":1,\"height\":1}";
private static final String jsonPartialMixin = "{\"name\":\"A\",\"email\":\"a@a\",\"password\":\"\",\"width\":1,\"height\":1}";
private static final User user = new User("A", "a@a", "a", 1, 1);
private static final ObjectMapper mapperMixin = new ObjectMapper();
static {
mapperMixin.addMixIn(User.class, UserMixin.class);
}
@Test
public void serializeDeserializeUsingMixin() throws IOException {
assertEquals(user, mapperMixin.readValue(jsonFull, User.class));
assertEquals(jsonPartialMixin, mapperMixin.writeValueAsString(user));
}
}
那是用户 class。
class User {
private String name;
private String email;
private transient String password;
private int width;
private int height;
public User() {
}
User(String name, String email, String password, int width, int height) {
this.name = name;
this.email = email;
this.password = password;
this.width = width;
this.height = height;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Float.compare(user.width, width) == 0 &&
Float.compare(user.height, height) == 0 &&
Objects.equals(name, user.name) &&
Objects.equals(email, user.email) &&
Objects.equals(password, user.password);
}
@Override
public int hashCode() {
return Objects.hash(name, email, password, width, height);
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", email='" + email + '\'' +
", password='" + password + '\'' +
", width=" + width +
", height=" + height +
'}';
}
}
我在 JAX-RS 应用程序中使用 Jackson v2,我正在尝试弄清楚它是否可行 配置 "ObjectMapper" 以使用 transient 修饰符删除字段,但仅在序列化期间。
这是一个 DTO 来说明我的用例(省略了 getter 和 setter)
public class User {
private String email;
private transient String password;
}
考虑到上述 DTO,我希望有一个对象映射器可以删除 序列化时的密码字段,并在反序列化期间包含它。
关于瞬变,我唯一能找到的是:
MapperFeature.PROPAGATE_TRANSIENT_MARKER
但是那个配置与我的要求不相关。
P.S - 不使用注释,因为 DTO 不与任何库耦合,另外 我不一定能控制它们。
不知道,看起来 transient
属性修饰符加上 PROPAGATE_TRANSIENT_MARKER
就可以了。反序列化很简单。不过,在序列化期间有一些 fuss with the transient marker。您需要为字段提供吸气剂,否则您将陷入异常 "Unrecognized field ... not marked as ignorable".
为了满足额外的要求,我添加了一个使用 jackson mixins 的版本。请注意,mixin 版本会生成带有空密码字段的 json,而 PROPAGATE_TRANSIENT_MARKER 版本根本不会生成任何字段。
PROPAGATE_TRANSIENT_MARKER版本
public class SerializeDeserializeAttributes {
private final ObjectMapper mapper = new ObjectMapper();
public <T> T fromJson(String json, Class<T> c) throws IOException {
synchronized (mapper) {
mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, false);
return mapper.readValue(json, c);
}
}
public String toJson(Object o) throws JsonProcessingException {
synchronized (mapper) {
mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);
return mapper.writeValueAsString(o);
}
}
private static final String jsonFull = "{\"name\":\"A\",\"email\":\"a@a\",\"password\":\"a\",\"width\":1,\"height\":1}";
private static final String jsonPartial = "{\"name\":\"A\",\"email\":\"a@a\",\"width\":1,\"height\":1}";
private static final User user = new User("A", "a@a", "a", 1, 1);
@Test
public void serializeDeserialize() throws IOException {
assertEquals(user, fromJson(jsonFull, User.class));
assertEquals(jsonPartial, toJson(user));
assertEquals(user, fromJson(jsonFull, User.class));
assertEquals(jsonPartial, toJson(user));
}
}
Mixin版本
public class SerializeDeserializeAttributesMixin {
public abstract class UserMixin {
@JsonSerialize(using = PwdSerializer.class)
transient String password;
}
static class PwdSerializer extends StdSerializer<String> {
public PwdSerializer() {
this(String.class);
}
private PwdSerializer(Class<String> t) {
super(t);
}
@Override
public void serialize(String s, JsonGenerator jg, SerializerProvider sp) throws IOException {
jg.writeString("");
}
}
private static final String jsonFull = "{\"name\":\"A\",\"email\":\"a@a\",\"password\":\"a\",\"width\":1,\"height\":1}";
private static final String jsonPartialMixin = "{\"name\":\"A\",\"email\":\"a@a\",\"password\":\"\",\"width\":1,\"height\":1}";
private static final User user = new User("A", "a@a", "a", 1, 1);
private static final ObjectMapper mapperMixin = new ObjectMapper();
static {
mapperMixin.addMixIn(User.class, UserMixin.class);
}
@Test
public void serializeDeserializeUsingMixin() throws IOException {
assertEquals(user, mapperMixin.readValue(jsonFull, User.class));
assertEquals(jsonPartialMixin, mapperMixin.writeValueAsString(user));
}
}
那是用户 class。
class User {
private String name;
private String email;
private transient String password;
private int width;
private int height;
public User() {
}
User(String name, String email, String password, int width, int height) {
this.name = name;
this.email = email;
this.password = password;
this.width = width;
this.height = height;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Float.compare(user.width, width) == 0 &&
Float.compare(user.height, height) == 0 &&
Objects.equals(name, user.name) &&
Objects.equals(email, user.email) &&
Objects.equals(password, user.password);
}
@Override
public int hashCode() {
return Objects.hash(name, email, password, width, height);
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", email='" + email + '\'' +
", password='" + password + '\'' +
", width=" + width +
", height=" + height +
'}';
}
}