Jackson序列化:外部类仅序列化带JsonView字段,嵌套类全字段保留方案
问题分析与解决方案
你的推测完全正确:当禁用MapperFeature.DEFAULT_VIEW_INCLUSION后,Jackson的视图规则会递归应用到所有嵌套对象上。也就是说,即使Test类中的nestedObj字段标记了@JsonView(ConvertView.class),但NestedTest类的字段没有对应的@JsonView注解,Jackson会认为这些字段不属于当前视图,最终导致nestedObj的内容无法被序列化(如果nestedObj已初始化,会输出空对象;如果未初始化则输出null)。
要实现「仅外部类Test禁用无JsonView字段的序列化,嵌套类NestedTest不受限制」的需求,有以下几种可行方案:
方案1:给NestedTest添加类级别@JsonView注解
如果有权限修改NestedTest类的源码,直接在类上标记@JsonView(ConvertView.class),这样它的所有字段都会自动继承该视图规则,序列化时会被完整包含:
import com.fasterxml.jackson.annotation.JsonView; @JsonView(ConvertView.class) class NestedTest{ int n; String s; }
这种方法最简单直接,适合你能控制NestedTest代码的场景。
方案2:针对NestedTest单独启用DEFAULT_VIEW_INCLUSION
如果不想修改实体类源码,可以通过ObjectMapper的配置,为NestedTest类单独开启默认视图包含特性,覆盖全局的禁用设置:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.MapperFeature; // 初始化ObjectMapper并全局禁用DEFAULT_VIEW_INCLUSION ObjectMapper mapper = new ObjectMapper(); mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION); // 针对NestedTest类重新启用DEFAULT_VIEW_INCLUSION mapper.configOverride(NestedTest.class) .set(MapperFeature.DEFAULT_VIEW_INCLUSION, Boolean.TRUE); // 创建带视图的ObjectWriter并序列化 Test test = new Test(); test.nestedObj = new NestedTest(); // 记得初始化嵌套对象 test.a = 10; test.nestedObj.n = 20; test.nestedObj.s = "test"; ObjectWriter writer = mapper.writer().withView(ConvertView.class); String s = writer.writeValueAsString(test); System.out.println(s); // 输出结果:{"a":10,"nestedObj":{"n":20,"s":"test"}}
方案3:使用Mixin类(适合第三方类无法修改的场景)
如果NestedTest是第三方库中的类,无法修改源码,可以通过Jackson的Mixin特性,动态为它添加类级别@JsonView注解:
import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.MapperFeature; // 定义Mixin类,模拟添加类级别JsonView @JsonView(ConvertView.class) abstract class NestedTestMixin {} // 初始化ObjectMapper并注册Mixin ObjectMapper mapper = new ObjectMapper(); mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION); mapper.addMixIn(NestedTest.class, NestedTestMixin.class); // 序列化逻辑同方案2 Test test = new Test(); test.nestedObj = new NestedTest(); test.a = 10; test.nestedObj.n = 20; test.nestedObj.s = "test"; ObjectWriter writer = mapper.writer().withView(ConvertView.class); String s = writer.writeValueAsString(test); System.out.println(s);
以上三种方案都能满足你的需求,你可以根据实际场景选择最合适的一种。
内容的提问来源于stack exchange,提问作者Gaurang Singhal
相关产品推荐
相关产品推荐

