返回值是外部嵌套类-如何使用 @JsonView

189 天前
 cryboy007

前提

项目中都会使用 Result 作为接口返回值,分页查询接口中会使用 Result<PageInfo<T>>,T 是实际的返回对象,现在我想使用 @JsonView,发现返回值直接变为空了。我尝试在 ObjectMapper 中增加 Result 的 Serializer 确实可以满足我的要求。但是感觉不太优化,所有接口返回值都是 Result ,影响太大.
下面是我的代码片段

	@Bean
	public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
		ObjectMapper objectMapper = builder.createXmlMapper(false).build();
		SimpleModule simpleModule = new SimpleModule();
		simpleModule.addSerializer(Result.class, new ResultJsonSerializer(objectMapper));
		objectMapper.registerModule(simpleModule);

		return objectMapper;
	}
    
    @Override
    public void serialize(Result<T> page, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {
        gen.writeStartObject();

        gen.writeStringField("code", page.getCode());
        gen.writeStringField("msg", page.getMsg());
        gen.writeStringField("timestamp", page.getTimestamp());
        gen.writeStringField("requestId", page.getRequestId());
        gen.writeFieldName("data");  // 将 "data" 字段名称写入
        if (page.getData() instanceof PageInfo) {
            gen.writeStartObject();  // 开始 JSON 对象
            gen.writeBooleanField("isFirstPage", ((PageInfo<?>) page.getData()).isIsFirstPage());
            gen.writeBooleanField("hasNextPage", ((PageInfo<?>) page.getData()).isHasNextPage());
            gen.writeBooleanField("isLastPage", ((PageInfo<?>) page.getData()).isIsLastPage());
            gen.writeBooleanField("hasPreviousPage", ((PageInfo<?>) page.getData()).isHasPreviousPage());

            gen.writeNumberField("pages", ((PageInfo<?>) page.getData()).getPages());
            gen.writeNumberField("nextPage", ((PageInfo<?>) page.getData()).getNextPage());
            gen.writeNumberField("navigatePages", ((PageInfo<?>) page.getData()).getNavigatePages());
            gen.writeNumberField("pageNum", ((PageInfo<?>) page.getData()).getPageNum());
            gen.writeNumberField("pageSize", ((PageInfo<?>) page.getData()).getPageSize());
            gen.writeNumberField("size", ((PageInfo<?>) page.getData()).getSize());
            gen.writeNumberField("prePage", ((PageInfo<?>) page.getData()).getPrePage());
            gen.writeNumberField("navigateFirstPage", ((PageInfo<?>) page.getData()).getNavigateFirstPage());
            gen.writeNumberField("navigateLastPage", ((PageInfo<?>) page.getData()).getNavigateLastPage());
            gen.writeNumberField("startRow", ((PageInfo<?>) page.getData()).getStartRow());
            gen.writeNumberField("endRow", ((PageInfo<?>) page.getData()).getEndRow());
            gen.writeNumberField("total", ((PageInfo<?>) page.getData()).getTotal());
            gen.writeArrayFieldStart("list");
            objectMapper.writerWithView(serializerProvider.getActiveView()).writeValue(gen, ((PageInfo<?>) page.getData()).getList());
            gen.writeEndArray();
            gen.writeEndObject();  // 结束 JSON 对象
        }else {
            objectMapper.writerWithView(serializerProvider.getActiveView()).writeValue(gen, page.getData());
        }

        gen.writeEndObject();
    }
    

592 次点击
所在节点    Java
2 条回复
mmdsun
189 天前
再之前那个帖子也回复了你哈,说一个我的方法:这种情况嵌套类每一层 Result 和 PageInfo 、T 都需要加 @JsonView 的注解。你返回为空可能就是因为嵌套类中有类没有加 @JsonView 。这个注解可以加到类上的,效果就是所有字段控制都可见。

另外在控制器上使用的 T 类的(假设是 Apple 类)
@JsonView(AppleView.class),你可能会说这三个类 Result<PageInfo<Apple>>是怎么关联的? 还有一个重要的步骤就是 AppleView 接口需要继承 Result 、PageInfo 的 View 接口。(Java 接口支持多继承)

——这样不会改动很多,因为默认还是所有字段可见的。你只需要控制的时候在对 T 类用 @JsonView 控制就行。(可能还有其他更好的方法就要查文档了,我也记得不是很清楚。
cryboy007
189 天前
@mmdsun 十分感谢,按照你提供的方式 可以的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/987971

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX