我试图序列化一个我无法触及任何内容的课程。问题是我想忽略一些 getWhatever() getter方法,但我不能用 @JsonIgnore 标记getter方法,因为这意味着要触及DTO类。
该序列化是在Spring REST Web服务上通过 @RestController 方法进行的,所以如果它可以成为一个解决方案,那就太棒了。
我想到了一个我不喜欢的解决方案......它会为我要序列化的DTO类创建一个自定义序列化器,所以我可以控制什么序列化,什么不是,然后,来自 @RestController ,而不是返回DTO类(我认为这更优雅),在获取带有 ObjectMapper的JSON字符串后返回 String 并强制使用自定义序列化程序。
我不喜欢这个解决方案:
提前感谢您...非常感谢任何帮助
编辑(解决方案) 由于@Cassio Mazzochi Molin的想法,我终于采用了这个解决方案:
interface FooMixIn {
@JsonIgnore
Object getFoo();
@JsonIgnore
Object getBar();
}
@Service
public class ServiceFooSerializer extends SimpleModule{
public ServiceFooSerializer(){
this.setMixInAnnotation(Foo.class, FooMixIn.class);
}
}
答案 0 :(得分:1)
在this answer的帮助下并基于Spring Boot Example
这是一个看起来相同的DTO1和DTO2类(getter和setter未显示):
public class DTO1 {
private String property1;
private String property2;
private String property3;
这是一个用于测试的控制器:
@RestController
public class HelloController {
@RequestMapping("/dto1")
public ResponseEntity<DTO1> dto1() {
return new ResponseEntity<DTO1>(new DTO1("prop1", "prop2", "prop3"), HttpStatus.OK);
}
@RequestMapping("/dto2")
public ResponseEntity<DTO2> dto2() {
return new ResponseEntity<DTO2>(new DTO2("prop1", "prop2", "prop3"), HttpStatus.OK);
}
}
这是我的WebConfig
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Bean
public MappingJackson2HttpMessageConverter customJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
MyBeanSerializerFactory customSerializationFactory = new MyBeanSerializerFactory(new SerializerFactoryConfig());
customSerializationFactory.getClasses().add(DTO1.class);
customSerializationFactory.getFieldsToIgnore().add("property2");
objectMapper.setSerializerFactory(customSerializationFactory);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
jsonConverter.setObjectMapper(objectMapper);
return jsonConverter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(customJackson2HttpMessageConverter());
}
}
这是自定义BeanserializerFactory:
public class MyBeanSerializerFactory extends BeanSerializerFactory {
private Set<Class> classes = new HashSet<>();
private Set<String> fieldsToIgnore = new HashSet<>();
protected MyBeanSerializerFactory(SerializerFactoryConfig config) {
super(config);
// TODO Auto-generated constructor stub
}
public Set<Class> getClasses() {
return classes;
}
public Set<String> getFieldsToIgnore() {
return fieldsToIgnore;
}
@Override
protected void processViews(SerializationConfig config, BeanSerializerBuilder builder) {
super.processViews(config, builder);
// ignore fields only for concrete class
// note, that you can avoid or change this check
if (classes.contains(builder.getBeanDescription().getBeanClass())) {
// get original writer
List<BeanPropertyWriter> originalWriters = builder.getProperties();
// create actual writers
List<BeanPropertyWriter> writers = new ArrayList<BeanPropertyWriter>();
for (BeanPropertyWriter writer : originalWriters) {
String propName = writer.getName();
// if it isn't ignored field, add to actual writers list
if (!fieldsToIgnore.contains(propName)) {
writers.add(writer);
}
}
builder.setProperties(writers);
}
}
}
这是一个测试,显示从DTO1中删除的属性2,但不是DTO2:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {
@Autowired
private MockMvc mvc;
@Test
public void test1() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/dto1").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(content().string(equalTo("{\"property1\":\"prop1\",\"property3\":\"prop3\"}")));
mvc.perform(MockMvcRequestBuilders.get("/dto2").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(content()
.string(equalTo("{\"property1\":\"prop1\",\"property2\":\"prop2\",\"property3\":\"prop3\"}")));
}
}
有关上述代码,请参阅https://github.com/gregclinker/json-mapper-example。
答案 1 :(得分:1)
如果无法修改类,则可以使用混合注释。
您可以将其视为在运行时添加更多注释的面向方面的方式,以增加静态定义的注释。
首先定义一个混合注释界面(一个类也可以):
public interface FooMixIn {
@JsonIgnore
Object getWhatever();
}
然后配置ObjectMapper
以将定义的界面用作POJO的混合:
ObjectMapper mapper = new ObjectMapper().addMixIn(Foo.class, FooMixIn.class);
一些使用注意事项:
private
,protected
,...)和方法实现被忽略。有关详细信息,请查看杰克逊documentation。