Spring boot Jackson Json Serialization for List 实现类(PagedList)
Posted
技术标签:
【中文标题】Spring boot Jackson Json Serialization for List 实现类(PagedList)【英文标题】:Spring boot Jackson Json Serialization for List implementation class (PagedList) 【发布时间】:2016-09-18 18:32:16 【问题描述】:有没有办法为具有自定义属性的列表实现类添加序列化?
我正在使用 Spring-boot 1.3 开发 Rest 服务。我必须以 Paged-List 或 Normal-List 的形式返回 JSON 响应,具体取决于 Controller 上的请求。所以,我必须将控制器方法的返回类型保持为通用public List<Employee> getEmployees(int departmentId)
我正在实现如下列表(使用泛型用于不同的对象列表)
public class PagedList<E> implements List<E>
private List<E> list;
private long totalRecords; //Getter-setters are added
public PagedList(List<E> list)
super();
this.list = list;
public PagedList(List<E> list, long totalRecords)
super();
this.list = list;
this.totalRecords = totalRecords;
@Override
public boolean add(E element)
return this.list.add(element);
//All other List abstract methods implemented same as above using this.list
为相同添加了JsonSerializer:public class PagedListSerializer extends JsonSerializer<PagedList>
,serialize()
方法中的序列化逻辑。使用spring-boot jackson customization注册:
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder()
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.serializerByType(PagedList.class, new PagedListSerializer());
return builder;
当我尝试return PagedList<Employee>(list, 1000)
时,我无法得到以下回复。它的返回与普通列表相同。不执行自定义序列化。如何获得以下分页响应?
list : [employeeId: "1", name: "John" , ... ],
totalRecords : 1000
【问题讨论】:
【参考方案1】:您可能不需要自定义反序列化器来获取此 json。只需在您的课程中添加 @JsonFormat(shape = JsonFormat.Shape.OBJECT)
注释即可:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public static class PagedList<E> implements List<E>
@JsonProperty
private List<E> list;
@JsonProperty // no need for this if you have getter-setters
private long totalRecords;
@JsonIgnore
@Override
public boolean isEmpty()
return false;
...
这里是完整的演示:https://gist.github.com/varren/35c4ede769499b1290f98e39a2f85589
cmets 后更新:
我认为 Spring 使用 Jacksons return mapper.writerFor(List.class).writeValueAsString(new MyList());
这是演示:
@RestController
@RequestMapping(value="/")
public static class MyRestController
private static final ObjectMapper mapper = new ObjectMapper();
//returns [] for both 0 and 1
@RequestMapping(value="test", method = RequestMethod.GET)
public List test(@RequestParam int user)
return user == 0 ? new ArrayList(): new MyList();
//returns [] for 0 and expected custom "empty": true for 1
@RequestMapping(value="testObj", method = RequestMethod.GET)
public Object testObj(@RequestParam int user)
return user == 0 ? new ArrayList(): new MyList();
// returns expected custom "empty": true
@RequestMapping(value="testMyList", method = RequestMethod.GET)
public MyList testMyList()
return new MyList();
// returns expected custom "empty": true
@RequestMapping(value="testMyListMapper", method = RequestMethod.GET)
public String testMyListMapper() throws JsonProcessingException
return mapper.writeValueAsString(new MyList());
// returns []
@RequestMapping(value="testMyListMapperListWriter", method = RequestMethod.GET)
public String testMyListMapperListWriter() throws JsonProcessingException
return mapper.writerFor(List.class).writeValueAsString(new MyList());
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public static class MyList extends ArrayList
所以您必须选项 1)返回 Object
而不是 List
或 选项 2)为 List 注册自定义序列化程序(而不是 PageList)builder.serializerByType(List.class, new PagedListSerializer());
像这样:
public class PagedListSerializer extends JsonSerializer<List>
@Override
public void serialize(List valueObj, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException
if (valueObj instanceof PagedList)
PagedList value = (PagedList) valueObj;
gen.writeStartObject();
gen.writeNumberField("totalRecords", value.getTotalRecords());
gen.writeObjectField("list", value.getList());
gen.writeEndObject();
else
gen.writeStartArray();
for(Object obj : valueObj)
gen.writeObject(obj);
gen.writeEndArray();
【讨论】:
我尝试使用@JsonFormat(shape = JsonFormat.Shape.OBJECT)
和@JsonProperty
。但它不适用于 Spring 的 rest 服务。 ObjectMapper 没有使用 writeValueAsString() 方法。这是我的源代码供参考 - Spring-boot-jdbc-template
@GovindSomani 很棒的演示。您遇到的问题是您使用 ListList
。正如实际问题中提到的,我也必须以正常列表的形式返回,这取决于相同 api 请求 的请求参数。所以,我不能每次都以PagedList<E>
的身份返回。 eg 中的新 dao 文件
@GovindSomani 更新了我的帖子。我认为您将不得不注册列表序列化程序而不是PagedList
,但老实说,这有点奇怪。在客户端将很难解析这个 json。客户端将不得不期待来自服务器的对象 OR 数组,并且使用某些库进行设置可能会很痛苦。
@GovindSomani 顺便说一句,Jackson 通常可以很好地理解对象类型,但我认为其中涉及一些弹簧包装器对象或列表序列化的一些错误,它弄乱了响应 实际上我认为除了在控制器中返回 Object
之外不需要更改任何内容 i.gyazo.com/9837906d67fd1d994ae61061dc1cb689.png【参考方案2】:
您可以创建您的 customObject Mapper 并在那里使用您的序列化程序。
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="custom.CustomObjectMapper"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
【讨论】:
我们可以将 ObjectMapper 定义为 bean 来覆盖默认值。您能否提供更多详细信息来编写自定义序列化?这是我的源代码供参考-Spring-boot-jdbc-template @GovindS 您是否能够为对象列表实现自定义序列化。我也在尝试做同样的事情,但自定义序列化程序没有被执行。 @Monisha,是的。您可以参考 [this|***.com/a/37367400/6108027] 答案以供参考。是否使用相同的配置?以上是关于Spring boot Jackson Json Serialization for List 实现类(PagedList)的主要内容,如果未能解决你的问题,请参考以下文章
尝试通过 Spring Boot Rest 使用 Jackson 验证 JSON
Spring Boot (Jackson):如何避免类名被序列化为 JSON
Spring MVC 接收的 JSON 嵌套对象的 Spring Boot JACKSON 配置