[英]Jackson multiple different schema for serialization of nested fields
使用 Jackson 进行序列化时,我希望有几种不同的模式。 假设我有以下课程:
public class Department {
private Person head;
private Person deputy;
private List<Person> staff;
// getters and setters
}
public class Person {
private String name
private int code;
// getters and setters
}
现在,我想为Department
class 提供两种不同的架构。 第一个只包含head
和deputy
,其中head
包括name
和code
,但deputy
只有name
。 第二个模式应该递归地包含所有字段。
因此,我们将有两个不同的 json。 使用第一个模式:
{
"head" : {
"name" : "John",
"code" : 123
},
"deputy" : {
"name" : "Jack"
}
}
,并使用第二个模式:
{
"head" : {
"name" : "John",
"code" : 123
},
"deputy" : {
"name" : "Jack",
"code" : "234"
},
"staff": [
{
"name" : "Tom",
"code" : "345"
},
{
"name" : "Matt",
"code" : "456"
},
]
}
问题:我应该如何处理 Jackson?
注意:这些类只是示例。 对于这个简单的示例,编写四个不同的包装类可能是可能的,但考虑一个包含十几个类的复杂示例,每个类都有多个字段。 使用包装类,我们应该生成很多样板代码。
任何帮助,将不胜感激!
尽管@bigbounty 解决方案非常好,而且我认为除了特定的DTO
之外, View
通常是通往 go 的方式,但在这种情况下它可能不适用,因为对于同一个 class Person
,我们实际上需要两种不同的行为在同一个视图中。
@JsonFilter
可以用来解决问题。
这个main
方法计算你需要的图表:
public static void main(String[] args) throws JsonProcessingException {
final PropertyFilter departmentFilter = new SimpleBeanPropertyFilter() {
@Override
public void serializeAsField
(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
throws Exception {
if (include(writer)) {
final String name = writer.getName();
if (!name.equals("deputy") && !name.equals("staff")) {
writer.serializeAsField(pojo, jgen, provider);
return;
}
if (name.equals("staff")) {
return;
}
// Ideally it should not be muted.
final Department department = (Department)pojo;
final Person deputy = department.getDeputy();
deputy.setCode(-1);
writer.serializeAsField(department, jgen, provider);
} else if (!jgen.canOmitFields()) { // since 2.3
writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return true;
}
@Override
protected boolean include(PropertyWriter writer) {
return true;
}
};
final PropertyFilter personFilter = new SimpleBeanPropertyFilter() {
@Override
public void serializeAsField
(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
throws Exception {
if (include(writer)) {
if (!writer.getName().equals("code")) {
writer.serializeAsField(pojo, jgen, provider);
return;
}
int code = ((Person) pojo).getCode();
if (code >= 0) {
writer.serializeAsField(pojo, jgen, provider);
}
} else if (!jgen.canOmitFields()) { // since 2.3
writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return true;
}
@Override
protected boolean include(PropertyWriter writer) {
return true;
}
};
final Department department = new Department();
final Person head = new Person("John", 123);
final Person deputy = new Person("Jack", 234);
final List<Person> personList = Arrays.asList(new Person("Tom", 345), new Person("Matt", 456));
department.setHead(head);
department.setDeputy(deputy);
department.setStaff(personList);
final ObjectMapper mapper = new ObjectMapper();
final FilterProvider schema1Filters = new SimpleFilterProvider()
.addFilter("deparmentFilter", departmentFilter)
.addFilter("personFilter", personFilter)
;
mapper.setFilterProvider(schema1Filters);
final String withSchema1Filters = mapper.writeValueAsString(department);
System.out.printf("Schema 1:\n%s\n", withSchema1Filters);
// You must maintain the filters once the classes are annotated with @JsonFilter
// We can use two no-op builtin filters
final FilterProvider schema2Filters = new SimpleFilterProvider()
.addFilter("deparmentFilter", SimpleBeanPropertyFilter.serializeAll())
.addFilter("personFilter", SimpleBeanPropertyFilter.serializeAll())
;
mapper.setFilterProvider(schema2Filters);
final String withSchema2Filters = mapper.writeValueAsString(department);
System.out.printf("Schema 2:\n%s\n", withSchema2Filters);
}
要使此代码正常工作,您必须使用以下内容注释Department
class:
@JsonFilter("deparmentFilter")
还有Person
class :
@JsonFilter("personFilter")
如您所见,Jackson 还提供了几个内置过滤器。
此代码与您提出的测试类非常耦合,但可以以使其更通用的方式进行扩展。
请查看SimpleBeanPropertyFilter以获取有关如何创建自己的过滤器的示例。
Jackson 库中有一个功能 JsonViews。
您需要有一个 class 的意见
public class Views {
public static class Normal{}
public static class Extended extends Normal{}
}
接下来你注释系class
import com.fasterxml.jackson.annotation.JsonView;
import java.util.List;
public class Department {
@JsonView(Views.Normal.class)
private Person head;
@JsonView(Views.Normal.class)
private Person deputy;
@JsonView(Views.Extended.class)
private List<Person> staff;
public Person getHead() {
return head;
}
public void setHead(Person head) {
this.head = head;
}
public Person getDeputy() {
return deputy;
}
public void setDeputy(Person deputy) {
this.deputy = deputy;
}
public List<Person> getStaff() {
return staff;
}
public void setStaff(List<Person> staff) {
this.staff = staff;
}
}
保持人 class 原样
public class Person {
private String name;
private int code;
public Person(String name, int code) {
this.name = name;
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
在主function中,你在序列化object的地方,需要开启相应的视图。
public class Main {
static Department createDepartment(){
Department department = new Department();
Person head = new Person("John", 123);
Person deputy = new Person("Jack", 234);
List<Person> personList = Arrays.asList(new Person("Tom", 345), new Person("Matt", 456));
department.setHead(head);
department.setDeputy(deputy);
department.setStaff(personList);
return department;
}
public static void main(String[] args) throws JsonProcessingException {
Department department = createDepartment();
ObjectMapper mapper = new ObjectMapper();
String normal = mapper.writerWithView(Views.Normal.class).writeValueAsString(department);
String extended = mapper.writerWithView(Views.Extended.class).writeValueAsString(department);
System.out.println("Normal View - " + normal);
System.out.println("Extended View - " + extended);
}
}
output如下:
Normal View - {"head":{"name":"John","code":123},"deputy":{"name":"Jack","code":234}}
Extended View - {"head":{"name":"John","code":123},"deputy":{"name":"Jack","code":234},"staff":[{"name":"Tom","code":345},{"name":"Matt","code":456}]}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.