JsonView和统一封装返回结果的问题
来源:3-3 用户详情请求

醒着长眠
2021-03-02
老师您好,项目里很多时候使用统一封装返回结果,例如课程中的SimpleResponse类。
public class User {
public interface UserInfo{};
public interface UserDetail extends UserInfo{};
private String username;
private String password;
@JsonView(UserInfo.class)
public String getUsername() {
return username;
}
@JsonView(UserDetail.class)
public String getPassword() {
return password;
}
}
@RequestMapping("/user")
@JsonView(User.UserInfo.class)
public User getUser(@RequestParam String username){
User user = new User();
user.setUsername("123");
user.setPassword("123");
return user;
}
@RequestMapping("/user")
@JsonView(User.UserInfo.class)
public SimpleResponse getUser(@RequestParam String username){
User user = new User();
user.setUsername("123");
user.setPassword("123");
return new SimpleResponse(user);
}
在第一个返回中 可以只给前端展示username属性
但是在第二个返回中 用SimpleResponse包装了User对象后,JsonView就失效了,在前端无法获取到User对象的数据。
想问下老师这种包装数据可不可以用@JsonView控制
谢谢老师
2回答
-
这个问题我也遇到了,我认为主要发生这个问题的原因在于:将原本的所要进行JsonView视图过滤的A对象置于B对象中。B类我称为包装类,而包装类没有进行JsonView设置。在Controller返回值进行序列化时,包装类没有匹配的JsonView,则全部将其过滤掉了,以至于没有数据返回。
解决思路有2个方向:在包装类中添加JsonView注解。
重写包装类的序列化规则
第一个方向的思路
如果包装类是本项目的类,那只要在包装类的对象中同样添加JsonView就可以了。
如果包装类是其他框架引用的类,例如我所遇到的MyBatisPlus的分页对象Page,这种无法修改源码的情况,则考虑2种方法:
1. 重写Page对象,将新对象添加JsonView注解,然后返回时将原Page对象复制到新Page对象。
2. 通过反射,为Page对象动态添加JsonView注解。
这个思路我没有尝试下去,我认为这个思路虽然可行,但对代码的入侵性太大,不予考虑。主要尝试了第二种方案。
第二个方向的思路,重写Jackson对包装类的序列化规则。还是以MyBatisPlus的Page类为例
在不动原本代码的情况下,添加以下配置类:
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder){ ObjectMapper objectMapper = builder.createXmlMapper(false).build(); SimpleModule simpleModule = new SimpleModule(); simpleModule.addSerializer(Page.class, new PageJsonSerializer(objectMapper)); objectMapper.registerModule(simpleModule); return objectMapper; } }
public class PageJsonSerializer extends JsonSerializer<Page> { private ObjectMapper objectMapper; public PageJsonSerializer(ObjectMapper objectMapper){ this.objectMapper = objectMapper; } @Override public void serialize(Page page, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException { gen.writeStartObject(); gen.writeNumberField("total", page.getTotal()); gen.writeNumberField("size", page.getSize()); gen.writeNumberField("current", page.getCurrent()); gen.writeNumberField("pages", page.getPages()); gen.writeArrayFieldStart("records"); objectMapper.writerWithView(serializerProvider.getActiveView()).writeValue(gen, page.getRecords()); gen.writeEndArray(); gen.writeEndObject(); } }
逻辑很简单,应该不用再解释了。主要思路就是告诉Jackson,当需要序列化Page这个对象时,除了records里按指定的JsonView序列化,其他字段原样进行序列化。
012022-04-25 -
JoJo
2021-04-14
额...每太看明白问题,你能处理SimpleResponse,想处理SimpleResponse类中包装的返回结果的话,直接get获取到处理就好了。
012021-04-15
Spring Security技术栈开发企业级认证与授权
2662 学习 · 1561 问题
相似问题