我想用Jackson解析JSON文档,并在所有节点上应用一些转换。例如,假设我希望反序列化后所有值都为大写。
实际用例有点复杂:
杰克逊有足够的配置选项/挂钩,所以我很确定这是可能的,我找不到自己的方式。
下面的测试显示了我想要实现的目标:
public class JsonValueFilterTest {
private ObjectMapper mapper;
@Before
public void setupObjectMapper() {
mapper = new ObjectMapper();
// TODO: configure mapper to upper case all values
}
@Test
public void printJson() throws IOException {
Entity myEntity = new Entity("myName");
mapper.writeValue(System.out, myEntity); // prints: {"name":"myName"}
}
@Test
public void valuesAreUpperCasedWhenLoaded() throws IOException {
Entity myEntity = mapper.readValue("{\"name\":\"myName\"}", Entity.class);
assertThat(myEntity.getName()).isEqualTo("MYNAME"); // fails
}
public static class Entity {
private final String name;
@JsonCreator
public Entity(@JsonProperty("name") String name) { this.name = name; }
public String getName() { return name; }
@Override
public String toString() { return "name='" + name + "'"; }
}
}
答案 0 :(得分:4)
对于这种简单的情况,您可以使用转换器来实现自定义反序列化器。我不知道为什么,但它不是在创建者构造函数上工作。所以你必须使用非最终字段。
public class JsonValueFilterTest {
private ObjectMapper mapper;
@BeforeTest
public void setupObjectMapper() {
mapper = new ObjectMapper();
}
@Test
public void printJson() throws IOException {
Entity myEntity = new Entity("myName");
mapper.writeValue(System.out, myEntity); // prints: {"name":"myName"}
}
@Test
public void valuesAreUpperCasedWhenLoaded() throws IOException {
Entity myEntity = mapper.readValue("{\"name\":\"myName\"}", Entity.class);
Assert.assertEquals(myEntity.getName(), "MYNAME"); // fails
}
public static class UpCaseConverter extends StdConverter<String, String> {
public String convert(String value) {
return value==null ? null : value.toUpperCase();
}
}
public static class Entity {
private String name;
public Entity() {}
public Entity(String name) {
this.name = name;
}
@JsonDeserialize(converter = UpCaseConverter.class)
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "name='" + name + "'";
}
}
}
答案 1 :(得分:1)
我的最终解决方案(感谢Alban):
JsonNode
(这将应用转换)将JsonNode
转换为我的自定义类
public class JsonValueFilterTest {
private ObjectMapper mapper;
@Before
public void setupObjectMapper() {
mapper = new ObjectMapper();
mapper.setNodeFactory(new JsonNodeFactory() {
@Override
public TextNode textNode(String text) {
return super.textNode(text.toUpperCase());
}
});
}
@Test
public void printJson() throws IOException {
Entity myEntity = new Entity("myName");
mapper.writeValue(System.out, myEntity); // prints: {"name":"myName"}
}
@Test
public void valuesAreUpperCasedWhenLoaded() throws IOException {
JsonNode jsonNode = mapper.readTree("{\"name\":\"myName\"}");
Entity myEntity = mapper.treeToValue(jsonNode, Entity.class);
assertThat(myEntity.getName()).isEqualTo("MYNAME");
}
public static class Entity {
private final String name;
@JsonCreator
public Entity(@JsonProperty("name") String name) { this.name = name; }
public String getName() { return name; }
@Override
public String toString() { return "name='" + name + "'"; }
}
}