Java Web 开发中,对象转 JSON 是高频刚需。主流方案包括:官方 JSON-java(轻量)、Gson(Google)、FastJSON(阿里)、Jackson(Spring 默认)。本文对比各库特性,提供生产级封装工具类。
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 简单对象/少量数据 | JSON-java (org.json) | 仅 5 个类,零依赖,API 简洁 |
| 复杂对象/日期/泛型 | Jackson | Spring 生态默认,性能强,注解丰富 |
| 高性能/特殊序列化需求 | FastJSON | 极致性能,功能全,但需注意版本安全漏洞 |
| 注解驱动/字段过滤 | Gson | 注解体系完善,适合复杂字段控制 |
官方库不支持 List<Bean> 直接转换,需转为 List<Map>。针对「空值不输出」痛点,可修改源码 JSONObject.populateMap:
// 原逻辑:值为 null 不放入 map if (result != null) map.put(key, wrap(result)); // 修改后:空值输出空字符串 map.put(key, result == null ? "" : wrap(result));
public class ResponseJsonUtils {
// 全局序列化配置:空值友好输出
private static final SerializerFeature[] FEATURES = {
WriteMapNullValue, // Map null 值输出
WriteNullBooleanAsFalse, // Boolean null -> false
WriteNullListAsEmpty, // List null -> []
WriteNullNumberAsZero, // Number null -> 0
WriteNullStringAsEmpty, // String null -> ""
WriteDateUseDateFormat // 日期格式化
};
public static void json(HttpServletResponse resp, Object data) {
json(resp, data, "UTF-8");
}
public static void json(HttpServletResponse resp, Object data, String encoding) {
resp.setContentType("application/json;charset=" + encoding);
try (PrintWriter out = resp.getWriter()) {
out.write(JSON.toJSONString(data, FEATURES));
out.flush();
} catch (IOException e) {
throw new RuntimeException("JSON 输出失败", e);
}
}
// JSONP 支持
public static void jsonp(HttpServletResponse resp, String callback, Object data) {
String jsonp = callback + "(" + JSON.toJSONString(data, FEATURES) + ");";
resp.setContentType("application/javascript;charset=UTF-8");
try (PrintWriter out = resp.getWriter()) {
out.write(jsonp);
} catch (IOException e) {
throw new RuntimeException("JSONP 输出失败", e);
}
}
}
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/user")
public void getUser(HttpServletResponse response) {
Map<String, Object> data = Map.of(
"name", "张三", "age", 28, "tags", List.of("Java", "架构")
);
ResponseJsonUtils.json(response, data);
}
}
public class UserAction extends ActionSupport {
private String callback;
public void json() {
ResponseJsonUtils.json(ServletActionContext.getResponse(), buildData());
}
public void jsonp() {
ResponseJsonUtils.jsonp(ServletActionContext.getResponse(), callback, buildData());
}
}
@Component
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper() {
setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
setSerializationInclusion(JsonInclude.Include.ALWAYS); // 输出 null 字段
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}
}
// Spring MVC 配置
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired CustomObjectMapper mapper;
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter(mapper));
}
}
JSON 序列化看似简单,实则涉及空值处理、日期格式、大数精度、循环引用、安全漏洞等深层问题。建议:统一封装工具类、全局配置序列化策略、框架层面集成 MessageConverter,避免控制器层重复造轮子。技术选型上,Spring 生态首选 Jackson,高性能场景慎用 FastJSON 并及时升级版本。