场景:业务需要返回的json中,为null的字段也要返回,字符串赋值“”,数值赋值0.
项目中用的是springboot
处理前:
{
"createdAt": "2019-03-27 22:01:39",
"entId": "1"
}
处理后:
{
"basIsEnabled": "",
"createdAt": "2019-03-27 22:01:39",
"creatorCode": "",
"creatorName": "",
"creatorOrgCode": "",
"deleted": "1",
"dualOrgCode": "",
"dualOrgId": "",
"dualOrgName": "",
"entId": "1"
}
网上的做法一般是自定义一个消息转换器,这里我就不多介绍,主要是通过config.setSerializerFeatures实现:
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
/**
* 自定义FastJon转换Api返回对象
*
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
converter.setSupportedMediaTypes(
Arrays.asList(
new MediaType("application", "json", UTF8),
new MediaType("application", "*+json", UTF8)));
// 自定义配置,不序列化class属性
FastJsonConfig config = new FastJsonConfig();
PropertyPreFilter classFilter =
new PropertyPreFilter() {
@Override
public boolean apply(JSONSerializer serializer, Object object, String name) {
if (CLASS.equalsIgnoreCase(name)) {
return false;
}
return true;
}
};
SerializeConfig mapping = new SerializeConfig();
mapping.put(Date.class, new SimpleDateFormatSerializer(DATE_FORMAT));
mapping.put(java.sql.Date.class, new SimpleDateFormatSerializer(DATE_FORMAT));
mapping.put(Timestamp.class, new SimpleDateFormatSerializer(DATE_TIME_FORMAT));
config.setSerializeConfig(mapping);
config.setSerializeFilters(classFilter);
converter.setFastJsonConfig(config);
converters.add(converter);
//主要配置在这
config.setSerializerFeatures(
SerializerFeature.WriteNullStringAsEmpty, //转字符串
SerializerFeature.WriteNullListAsEmpty, //转list
SerializerFeature.WriteNullNumberAsZero, //转数值
SerializerFeature.WriteNullBooleanAsFalse //转boolean
);
// 处理JSON转换Pageable分页参数
ParserConfig.global.putDeserializer(
Pageable.class,
new JavaBeanDeserializer(ParserConfig.global, PageParam.class));
}
}
但是这种做法是全局的转换,也就是说所有的接口返回都会转。如果只需要部分接口做转换,就需要用aop
思路:定义一个aop,在返回响应体的时候对output进行处理,定义一个注解作为pointcut,这样只要在方法上加上了这个注解,都会进行返回值的处理
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ReturnJsonDiversion {
String value() default "";
}
@Aspect
@Component
public class RetrunJsonAspect {
/**
* @After (后置通知)
*
* @param point
* @return
* @throws Throwable
*/
@AfterReturning(pointcut = "@annotation(com.pagoda.intfc.api.aop.ReturnJsonDiversion)", returning = "returnValue")
public Object after(JoinPoint point, Object returnValue) {
ReturnResult returnResult = (ReturnResult) returnValue;
if (returnResult.getData() instanceof List) {
List<Object> dataList = (List) returnResult.getData();
dataList.forEach(o -> {
try {
Map<String, Field> objectMap = objMap(o);
for(Map.Entry<String,Field> m: objectMap.entrySet()) {
Object obj = m.getValue().get(o);
Class<?> clazz = m.getValue().getType();
if(Objects.isNull(obj)) {
if (clazz == Date.class || clazz == String.class) {
org.springframework.data.util.ReflectionUtils.setField(m.getValue(), o, "");
} else if (clazz == BigDecimal.class) {
org.springframework.data.util.ReflectionUtils.setField(m.getValue(), o, new BigDecimal(0));
} else if (clazz == Integer.class) {
org.springframework.data.util.ReflectionUtils.setField(m.getValue(), o, Integer.valueOf(0));
} else if (clazz == Float.class) {
org.springframework.data.util.ReflectionUtils.setField(m.getValue(), o, Float.valueOf(0));
} else if (clazz == Double.class) {
org.springframework.data.util.ReflectionUtils.setField(m.getValue(), o, Double.valueOf(0));
} else if (clazz == Long.class) {
org.springframework.data.util.ReflectionUtils.setField(m.getValue(), o, Long.valueOf(0));
} else if (clazz == Short.class) {
org.springframework.data.util.ReflectionUtils.setField(m.getValue(), o, 0);
} else if (clazz == Boolean.class) {
org.springframework.data.util.ReflectionUtils.setField(m.getValue(), o, 0);
} else if (clazz ==List.class){
org.springframework.data.util.ReflectionUtils.setField(m.getValue(), o, Lists.newArrayList());
}
else {
//3-6 未知类型直接赋值
org.springframework.data.util.ReflectionUtils.setField(m.getValue(), o, o);
}
}
}
} catch (Exception e) {
writeLog("RetrunJsonAspect.after", Constant.LOG_ERROR, "返回值转换数据异常:" + o.toString());
throw new BusinessException("数据转换异常:" + e.getMessage());
}
});
}
Object result = point.getTarget();
return result;
}
public Map<String,Field > objMap(Object obj) {
Map<String,Field> map = new HashMap<String,Field>(16);
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
ReflectionUtils.makeAccessible(field);
try {
map.put(field.getName(), field);
} catch (Exception e) {
writeLog("ReturnJsonDiversion.ObjMap", Constant.LOG_ERROR, "字段取值异常:" + field.getName());
throw new BusinessException("字段取值异常");
}
}
return map;
}
}
@PostMapping("/find")
@ReturnJsonDiversion
public ReturnResult find(@RequestBody Input input) {
ReturnResult output=xxService.find();
return output;
}
对aop概念和用法不理解的
传送门:
https://segmentfault.com/a/1190000007469968
https://segmentfault.com/a/1190000007469982