列表实现类的Spring boot Jackson Json序列化(PagedList)

时间:2021-06-20 18:01:43

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的请求。因此,我必须将控制器的返回类型作为通用公共列表 getEmployees(int department)

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 。使用spring-boot jackson定制注册:

@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, 1000)时,我无法得到以下响应。其返回与普通列表相同。不执行自定义序列化。如何跟踪页面响应?

{ 
  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>