Is there any way to add serialization for list implementing class having custom attributes?
是否有方法为具有自定义属性的实现类添加序列化?
I am working on Rest service using Spring-boot 1.3. I have to return JSON response as Paged-List or Normal-List, depend on request on Controller. So, I have to keep return type of controller method as generic public List<Employee> getEmployees(int departmentId)
我正在使用Spring-boot 1.3开发Rest服务。我必须返回JSON响应作为分页列表或常规列表,这取决于对Controller的请求。因此,我必须将控制器的返回类型作为通用公共列表
I am implementing list as below (using generics to use for different object lists)
我正在执行下面的列表(使用泛型来使用不同的对象列表)
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
}
Added JsonSerializer for same: public class PagedListSerializer extends JsonSerializer<PagedList>
with serialization logic in serialize()
method. Which is registered using spring-boot jackson customization :
添加了JsonSerializer: public class PagedListSerializer在serialize()方法中使用序列化逻辑扩展了JsonSerializer
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.serializerByType(PagedList.class, new PagedListSerializer());
return builder;
}
When I try to return PagedList<Employee>(list, 1000)
, I am not able to get following response. Its returning same as of normal list. Not executing custom serialization. How to get following paged response?
当我尝试返回PagedList
{
list : [{employeeId: "1", name: "John" }, ... ],
totalRecords : 1000
}
2 个解决方案
#1
1
You probably don't need custom deserializer to get this json. Just add @JsonFormat(shape = JsonFormat.Shape.OBJECT)
annotation to your class:
您可能不需要自定义反序列化器来获得这个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;
}
...
Here is full demo: https://gist.github.com/varren/35c4ede769499b1290f98e39a2f85589
这里有完整的演示:https://gist.github.com/varren/35c4ede769499b1290f98e39a2f85589
Update after comments:
更新后的评论:
I think Spring uses Jacksons return mapper.writerFor(List.class).writeValueAsString(new MyList());
Here is demo:
我认为Spring使用了Jacksons return mapper.writerFor(List.class)。writeValueAsString(新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 {}
So you have to Option 1) return Object
instead of List
or Option 2) register custom serialifer for List (and not for PageList) builder.serializerByType(List.class, new PagedListSerializer());
like this:
因此,您必须为List(而不是PageList) . serializerbytype (List)注册自定义的serialifer。类,新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();
}
}
}
#2
0
You can Create your customObject Mapper and use your serializer there.
您可以创建定制对象映射器,并在其中使用序列化器。
<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>
#1
1
You probably don't need custom deserializer to get this json. Just add @JsonFormat(shape = JsonFormat.Shape.OBJECT)
annotation to your class:
您可能不需要自定义反序列化器来获得这个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;
}
...
Here is full demo: https://gist.github.com/varren/35c4ede769499b1290f98e39a2f85589
这里有完整的演示:https://gist.github.com/varren/35c4ede769499b1290f98e39a2f85589
Update after comments:
更新后的评论:
I think Spring uses Jacksons return mapper.writerFor(List.class).writeValueAsString(new MyList());
Here is demo:
我认为Spring使用了Jacksons return mapper.writerFor(List.class)。writeValueAsString(新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 {}
So you have to Option 1) return Object
instead of List
or Option 2) register custom serialifer for List (and not for PageList) builder.serializerByType(List.class, new PagedListSerializer());
like this:
因此,您必须为List(而不是PageList) . serializerbytype (List)注册自定义的serialifer。类,新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();
}
}
}
#2
0
You can Create your customObject Mapper and use your serializer there.
您可以创建定制对象映射器,并在其中使用序列化器。
<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>