Java Jackson用于嵌套字段序列化的多个不同架构
我想在使用Jackson序列化时使用几种不同的模式。 假设我有以下几个类:Java Jackson用于嵌套字段序列化的多个不同架构,java,json,jackson,jackson-databind,Java,Json,Jackson,Jackson Databind,我想在使用Jackson序列化时使用几种不同的模式。 假设我有以下几个类: public class Department { private Person head; private Person deputy; private List<Person> staff; // getters and setters } public class Person { private String name pr
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
}
,并使用第二个模式:
{
"head" : {
"name" : "John",
"code" : 123
},
"deputy" : {
"name" : "Jack",
"code" : "234"
},
"staff": [
{
"name" : "Tom",
"code" : "345"
},
{
"name" : "Matt",
"code" : "456"
},
]
}
问题:我应该如何与杰克逊合作
注意:这些类只是示例。对于这个简单的示例,可以编写四个不同的包装器类,但请考虑一个包含十几个类的复杂示例,每个类都有几个字段。使用包装类,我们应该生成大量的样板代码
任何帮助都将不胜感激 Jackson库中有一个功能JsonViews 您需要为视图创建一个类
public class Views {
public static class Normal{}
public static class Extended extends Normal{}
}
接下来为Department类添加注释
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;
}
}
在序列化对象的main函数中,需要启用相应的视图
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);
}
}
尽管@bigbounty解决方案非常优秀,而且我认为除了特定的
DTO
s之外,View
s通常也是一种方式,但在这种情况下,它可能不适用,因为对于同一类Person
来说,我们实际上需要在同一个视图中有两种不同的行为
可以用来解决这个问题
此main
方法计算所需的图形:
公共静态void main(字符串[]args)引发JsonProcessingException{
final PropertyFilter departmentFilter=新的SimpleBeanPropertyFilter(){
@凌驾
公共空字段
(对象pojo、JsonGenerator jgen、SerializerProvider提供程序、PropertyWriter编写器)
抛出异常{
如果(包括(作者)){
最终字符串名=writer.getName();
如果(!name.equals(“代理”)和(&!name.equals(“职员”)){
writer.serializeAsField(pojo、jgen、provider);
返回;
}
如果(姓名等于(“员工”)){
返回;
}
//理想情况下,它不应该被静音。
最终部门=(部门)pojo;
最终人员代理=department.getsubsive();
代理主席:设定码(-1);
作者:Asfield(部门、jgen、供应商);
}如果(!jgen.canOmitFields()){//从2.3开始
writer.MittedField(pojo、jgen、提供者);
}
}
@凌驾
受保护的布尔值包括(BeanPropertyWriter){
返回true;
}
@凌驾
受保护的布尔值包括(PropertyWriter写入程序){
返回true;
}
};
final PropertyFilter personFilter=新的SimpleBeanPropertyFilter(){
@凌驾
公共空字段
(对象pojo、JsonGenerator jgen、SerializerProvider提供程序、PropertyWriter编写器)
抛出异常{
如果(包括(作者)){
如果(!writer.getName().equals(“code”)){
writer.serializeAsField(pojo、jgen、provider);
返回;
}
int code=((Person)pojo.getCode();
如果(代码>=0){
writer.serializeAsField(pojo、jgen、provider);
}
}如果(!jgen.canOmitFields()){//从2.3开始
writer.MittedField(pojo、jgen、提供者);
}
}
@凌驾
受保护的布尔值包括(BeanPropertyWriter){
返回true;
}
@凌驾
受保护的布尔值包括(PropertyWriter写入程序){
返回true;
}
};
最终部门=新部门();
最终负责人=新人(“约翰”,123);
最终代理人=新人(“杰克”,234);
最终列表personList=Arrays.asList(新人(“汤姆”,345),新人(“马特”,456));
部门。设置头(head);
副部长(副部长);
部门设置人员(人员列表);
最终ObjectMapper映射器=新ObjectMapper();
final FilterProvider Schema1 Filters=新的SimpleFilterProvider()
.addFilter(“deparmentFilter”,departmentFilter)
.addFilter(“personFilter”,personFilter)
;
setFilterProvider(Schema1过滤器);
最后一个字符串,带有chema1filters=mapper.writeValueAsString(department);
System.out.printf(“模式1:\n%s\n”,带有模式1筛选器);
//一旦类被@JsonFilter注释,您就必须维护过滤器
//我们可以使用两个无操作内置过滤器
final FilterProvider schema2Filters=新的SimpleFilterProvider()
.addFilter(“deparmentFilter”,SimpleBeanPropertyFilter.serializeAll())
.addFilter(“personFilter”,SimpleBeanPropertyFilter.serializeAll())
;
setFilterProvider(schema2Filters);
带有chema2filters=mapper.writeValueAsString(部门)的最终字符串;
System.out.printf(“模式2:\n%s\n”,带有模式2过滤器);
}
要使此代码正常工作,必须使用以下内容注释部门
类:
@JsonFilter(“deparmentFilter”)
以及人员
类:
@JsonFilter(“personFilter”)
如您所见,Jackson还提供了几个内置过滤器
此代码与您提出的测试类非常耦合,但可以通过使其更通用的方式对其进行扩展
请看一看如何创建您自己的过滤器的示例。谢谢您的详细回答。我熟悉JsonViews。但我认为这不能解决我的问题。例如,您的输出与我预期的json不同。因为映射程序总是在两个模式中完全相同地序列化
subsive
。但我想在每个模式中对其进行不同的序列化。您需要创建不同的视图。我是说,瓦希德雷扎伊的班级没有抓住你。你能再解释一下吗?你的意思是我必须为Person
类创建不同的视图吗?如果是肯定的,我应该如何在部门
类中注释副手
?@bigbounty的答案是正确的@vahidreza@JsonView可以接受一个视图数组。您可以注释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;
}
}
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);
}
}
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}]}