Java處理JSON編程實(shí)用技巧和性能優(yōu)化
1. 前言
JSON(JavaScript Object Notation)是一種輕量級(jí)的數(shù)據(jù)交換格式,易于閱讀和編寫,同時(shí)也易于機(jī)器解析和生成。在Java開(kāi)發(fā)中,JSON處理是一項(xiàng)非常常見(jiàn)且重要的任務(wù)。本文將詳細(xì)介紹Java中處理JSON的各種實(shí)用技巧,包括主流JSON框架的使用、性能優(yōu)化以及最佳實(shí)踐。
本文將重點(diǎn)介紹Gson、Jackson和Fastjson這三個(gè)主流Java JSON處理庫(kù)的使用技巧和性能優(yōu)化方法。
2. JSON處理框架對(duì)比
Java生態(tài)中有多個(gè)優(yōu)秀的JSON處理框架,每個(gè)框架都有其特點(diǎn)和適用場(chǎng)景。下面是三個(gè)主流框架的對(duì)比:

3. Gson使用技巧
3.1 基礎(chǔ)用法
Gson是Google開(kāi)發(fā)的Java庫(kù),用于將Java對(duì)象轉(zhuǎn)換為JSON表示,以及將JSON字符串轉(zhuǎn)換回等效的Java對(duì)象。
3.1.1 Maven依賴
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>3.1.2 基本序列化與反序列化
// 創(chuàng)建Gson實(shí)例
Gson gson = new Gson();
// Java對(duì)象轉(zhuǎn)JSON字符串
User user = new User("張三", 25);
String json = gson.toJson(user);
System.out.println(json); // {"name":"張三","age":25}
// JSON字符串轉(zhuǎn)Java對(duì)象
String jsonString = "{\"name\":\"李四\",\"age\":30}";
User parsedUser = gson.fromJson(jsonString, User.class);
System.out.println(parsedUser.getName()); // 李四3.1.3 集合類型的序列化與反序列化
// 序列化集合
List<User> userList = Arrays.asList(
new User("張三", 25),
new User("李四", 30)
);
String jsonList = gson.toJson(userList);
// 反序列化集合 - 方法1:使用TypeToken
Type userListType = new TypeToken<List<User>>(){}.getType();
List<User> parsedList = gson.fromJson(jsonList, userListType);
// 反序列化集合 - 方法2:先轉(zhuǎn)為數(shù)組再轉(zhuǎn)集合
User[] userArray = gson.fromJson(jsonList, User[].class);
List<User> userList2 = Arrays.asList(userArray);3.2 高級(jí)特性
3.2.1 GsonBuilder配置
Gson gson = new GsonBuilder()
.setPrettyPrinting() // 格式化輸出
.serializeNulls() // 序列化null值
.setDateFormat("yyyy-MM-dd HH:mm:ss") // 設(shè)置日期格式
.excludeFieldsWithoutExposeAnnotation() // 只序列化有@Expose注解的字段
.registerTypeAdapter(Date.class, new DateSerializer()) // 注冊(cè)自定義類型適配器
.disableHtmlEscaping() // 禁用HTML轉(zhuǎn)義
.create();3.2.2 自定義序列化和反序列化
// 自定義序列化器
public class UserSerializer implements JsonSerializer<User> {
@Override
public JsonElement serialize(User user, Type type, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("userName", user.getName()); // 字段名映射
jsonObject.addProperty("userAge", user.getAge());
return jsonObject;
}
}
// 自定義反序列化器
public class UserDeserializer implements JsonDeserializer<User> {
@Override
public User deserialize(JsonElement json, Type type, JsonDeserializationContext context)
throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
String name = jsonObject.get("userName").getAsString();
int age = jsonObject.get("userAge").getAsInt();
return new User(name, age);
}
}
// 注冊(cè)使用
Gson gson = new GsonBuilder()
.registerTypeAdapter(User.class, new UserSerializer())
.registerTypeAdapter(User.class, new UserDeserializer())
.create();3.2.3 使用注解控制序列化
public class User {
@SerializedName("user_name") // 字段重命名
private String name;
@SerializedName(value = "user_age", alternate = {"age", "userAge"}) // 多字段名映射
private int age;
@Expose(serialize = true, deserialize = false) // 控制序列化和反序列化
private String password;
@Expose(serialize = false, deserialize = true)
private String email;
// getter和setter方法...
}
// 注意:使用@Expose需要配合excludeFieldsWithoutExposeAnnotation()
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();3.2.4 處理復(fù)雜嵌套對(duì)象
// 使用JsonElement處理未知結(jié)構(gòu)的JSON
String complexJson = "{\"name\":\"張三\",\"address\":{\"city\":\"北京\",\"district\":\"朝陽(yáng)區(qū)\"}}";
JsonElement jsonElement = JsonParser.parseString(complexJson);
JsonObject jsonObject = jsonElement.getAsJsonObject();
// 獲取簡(jiǎn)單字段
String name = jsonObject.get("name").getAsString();
// 獲取嵌套對(duì)象的字段
JsonObject addressObject = jsonObject.getAsJsonObject("address");
String city = addressObject.get("city").getAsString();
// 安全地獲取可能不存在的字段
if (jsonObject.has("phone")) {
String phone = jsonObject.get("phone").getAsString();
}技巧:Gson 2.8.6+版本中,JsonParser的靜態(tài)方法已被棄用,建議使用以下方式:
Gson gson = new Gson(); JsonReader reader = new JsonReader(new StringReader(jsonString)); reader.setLenient(true); JsonElement jsonElement = gson.fromJson(reader, JsonElement.class);
4. Jackson使用技巧
4.1 基礎(chǔ)用法
Jackson是一個(gè)功能強(qiáng)大的Java庫(kù),用于處理JSON數(shù)據(jù)格式。它被廣泛應(yīng)用于Spring框架中,性能優(yōu)異且功能豐富。
4.1.1 Maven依賴
<!-- 核心依賴 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
<!-- 可選:處理XML -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.13.0</version>
</dependency>4.1.2 基本序列化與反序列化
// 創(chuàng)建ObjectMapper實(shí)例
ObjectMapper objectMapper = new ObjectMapper();
// Java對(duì)象轉(zhuǎn)JSON字符串
User user = new User("張三", 25);
String json = objectMapper.writeValueAsString(user);
System.out.println(json); // {"name":"張三","age":25}
// JSON字符串轉(zhuǎn)Java對(duì)象
String jsonString = "{\"name\":\"李四\",\"age\":30}";
User parsedUser = objectMapper.readValue(jsonString, User.class);
System.out.println(parsedUser.getName()); // 李四
// 格式化輸出JSON
String prettyJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);4.1.3 集合類型的序列化與反序列化
// 序列化集合
List<User> userList = Arrays.asList(
new User("張三", 25),
new User("李四", 30)
);
String jsonList = objectMapper.writeValueAsString(userList);
// 反序列化集合
List<User> parsedList = objectMapper.readValue(
jsonList,
new TypeReference<List<User>>() {}
);
// 反序列化為Map
Map<String, Object> map = objectMapper.readValue(
jsonString,
new TypeReference<Map<String, Object>>() {}
);4.2 高級(jí)特性
4.2.1 ObjectMapper配置
ObjectMapper objectMapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) // 忽略未知屬性
.configure(SerializationFeature.INDENT_OUTPUT, true) // 格式化輸出
.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false) // 不序列化null值
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) // 日期不使用時(shí)間戳
.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")) // 設(shè)置日期格式
.registerModule(new JavaTimeModule()); // 支持Java 8日期時(shí)間API4.2.2 自定義序列化和反序列化
// 自定義序列化器
public class UserSerializer extends JsonSerializer<User> {
@Override
public void serialize(User user, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("userName", user.getName());
jsonGenerator.writeNumberField("userAge", user.getAge());
jsonGenerator.writeEndObject();
}
}
// 自定義反序列化器
public class UserDeserializer extends JsonDeserializer<User> {
@Override
public User deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
String name = node.get("userName").asText();
int age = node.get("userAge").asInt();
return new User(name, age);
}
}
// 注冊(cè)使用
SimpleModule module = new SimpleModule();
module.addSerializer(User.class, new UserSerializer());
module.addDeserializer(User.class, new UserDeserializer());
objectMapper.registerModule(module);4.2.3 使用注解控制序列化
public class User {
@JsonProperty("user_name") // 字段重命名
private String name;
@JsonIgnore // 忽略此字段
private String password;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") // 日期格式化
private Date createTime;
@JsonInclude(JsonInclude.Include.NON_NULL) // 只序列化非null值
private String email;
@JsonInclude(JsonInclude.Include.NON_EMPTY) // 只序列化非空值
private List<String> hobbies;
// getter和setter方法...
}4.2.4 處理復(fù)雜JSON結(jié)構(gòu)
// 使用JsonNode處理未知結(jié)構(gòu)的JSON
String complexJson = "{\"name\":\"張三\",\"address\":{\"city\":\"北京\",\"district\":\"朝陽(yáng)區(qū)\"}}";
JsonNode rootNode = objectMapper.readTree(complexJson);
// 獲取字段
String name = rootNode.get("name").asText();
String city = rootNode.get("address").get("city").asText();
// 安全地獲取可能不存在的字段
if (rootNode.has("phone")) {
String phone = rootNode.get("phone").asText();
}
// 遍歷數(shù)組
JsonNode arrayNode = rootNode.get("contacts");
if (arrayNode != null && arrayNode.isArray()) {
for (JsonNode node : arrayNode) {
String contactName = node.get("name").asText();
}
}4.2.5 使用樹模型
// 創(chuàng)建樹模型
ObjectMapper mapper = new ObjectMapper();
ObjectNode rootNode = mapper.createObjectNode();
rootNode.put("name", "張三");
rootNode.put("age", 25);
// 創(chuàng)建嵌套對(duì)象
ObjectNode addressNode = mapper.createObjectNode();
addressNode.put("city", "北京");
addressNode.put("district", "朝陽(yáng)區(qū)");
rootNode.set("address", addressNode);
// 創(chuàng)建數(shù)組
ArrayNode hobbiesNode = mapper.createArrayNode();
hobbiesNode.add("讀書");
hobbiesNode.add("游泳");
rootNode.set("hobbies", hobbiesNode);
// 轉(zhuǎn)換為JSON字符串
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode);5. Fastjson使用技巧
5.1 基礎(chǔ)用法
Fastjson是阿里巴巴開(kāi)發(fā)的JSON庫(kù),以其極高的性能著稱,API簡(jiǎn)潔易用。
安全提示:Fastjson歷史上存在一些安全漏洞,使用時(shí)請(qǐng)確保更新到最新版本,并根據(jù)官方建議進(jìn)行安全配置。
5.1.1 Maven依賴
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.79</version>
</dependency>5.1.2 基本序列化與反序列化
// Java對(duì)象轉(zhuǎn)JSON字符串
User user = new User("張三", 25);
String json = JSON.toJSONString(user);
System.out.println(json); // {"age":25,"name":"張三"}
// JSON字符串轉(zhuǎn)Java對(duì)象
String jsonString = "{\"name\":\"李四\",\"age\":30}";
User parsedUser = JSON.parseObject(jsonString, User.class);
System.out.println(parsedUser.getName()); // 李四
// 格式化輸出
String prettyJson = JSON.toJSONString(user, SerializerFeature.PrettyFormat);5.1.3 集合類型的序列化與反序列化
// 序列化集合
List<User> userList = Arrays.asList(
new User("張三", 25),
new User("李四", 30)
);
String jsonList = JSON.toJSONString(userList);
// 反序列化集合
List<User> parsedList = JSON.parseArray(jsonList, User.class);
// 反序列化為JSONObject
JSONObject jsonObject = JSON.parseObject(jsonString);
String name = jsonObject.getString("name");
int age = jsonObject.getInteger("age");5.2 高級(jí)特性
5.2.1 SerializerFeature配置
// 配置序列化特性
String json = JSON.toJSONString(user,
SerializerFeature.PrettyFormat, // 格式化輸出
SerializerFeature.WriteNullStringAsEmpty, // null字符串輸出為""
SerializerFeature.WriteNullNumberAsZero, // null數(shù)字輸出為0
SerializerFeature.WriteNullBooleanAsFalse, // null布爾值輸出為false
SerializerFeature.WriteNullListAsEmpty, // null列表輸出為[]
SerializerFeature.DisableCircularReferenceDetect, // 禁用循環(huán)引用檢測(cè)
SerializerFeature.WriteDateUseDateFormat, // 日期格式化
SerializerFeature.WriteMapNullValue // 輸出null值
);5.2.2 自定義序列化和反序列化
// 自定義序列化器
public class UserSerializer implements ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
User user = (User) object;
SerializeWriter out = serializer.out;
out.write('{');
out.writeFieldName("userName");
serializer.write(user.getName());
out.write(',');
out.writeFieldName("userAge");
serializer.write(user.getAge());
out.write('}');
}
}
// 自定義反序列化器
public class UserDeserializer implements ObjectDeserializer {
@Override
public User deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
JSONObject jsonObject = parser.parseObject();
String name = jsonObject.getString("userName");
int age = jsonObject.getInteger("userAge");
return new User(name, age);
}
@Override
public int getFastMatchToken() {
return 0;
}
}
// 注冊(cè)使用
ParserConfig.getGlobalInstance().putDeserializer(User.class, new UserDeserializer());
SerializeConfig.getGlobalInstance().put(User.class, new UserSerializer());5.2.3 使用注解控制序列化
public class User {
@JSONField(name = "user_name") // 字段重命名
private String name;
@JSONField(serialize = false) // 不序列化此字段
private String password;
@JSONField(deserialize = false) // 不反序列化此字段
private String token;
@JSONField(format = "yyyy-MM-dd HH:mm:ss") // 日期格式化
private Date createTime;
@JSONField(ordinal = 1) // 字段序列化順序
private String email;
// getter和setter方法...
}5.2.4 使用JSONObject和JSONArray
// 創(chuàng)建JSONObject
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", "張三");
jsonObject.put("age", 25);
// 創(chuàng)建嵌套JSONObject
JSONObject addressObject = new JSONObject();
addressObject.put("city", "北京");
addressObject.put("district", "朝陽(yáng)區(qū)");
jsonObject.put("address", addressObject);
// 創(chuàng)建JSONArray
JSONArray hobbiesArray = new JSONArray();
hobbiesArray.add("讀書");
hobbiesArray.add("游泳");
jsonObject.put("hobbies", hobbiesArray);
// 轉(zhuǎn)換為JSON字符串
String json = jsonObject.toJSONString();
// 解析復(fù)雜JSON
JSONObject parsedObject = JSON.parseObject(complexJson);
String city = parsedObject.getJSONObject("address").getString("city");
JSONArray contacts = parsedObject.getJSONArray("contacts");
for (int i = 0; i < contacts.size(); i++) {
String contactName = contacts.getJSONObject(i).getString("name");
}5.2.5 安全配置
// 禁用AutoType,防止反序列化漏洞
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
// 如果需要使用AutoType,建議使用白名單機(jī)制
ParserConfig parserConfig = ParserConfig.getGlobalInstance();
parserConfig.addAccept("com.example.model."); // 只允許反序列化指定包下的類
// 或者使用安全的JSONReader
JSONReader jsonReader = new JSONReader(new StringReader(jsonString));
jsonReader.config(Feature.SupportAutoType, false);6. 性能優(yōu)化技巧
6.1 通用優(yōu)化原則
- 重用對(duì)象:避免重復(fù)創(chuàng)建JSON解析器實(shí)例(Gson、ObjectMapper或JSON),這些實(shí)例是線程安全的
- 避免不必要的轉(zhuǎn)換:直接在流上進(jìn)行操作,減少中間字符串的創(chuàng)建
- 選擇合適的解析模式:根據(jù)需求選擇樹模型或流式API
- 優(yōu)化數(shù)據(jù)結(jié)構(gòu):減少不必要的嵌套和冗余字段
- 合理使用緩存:緩存序列化/反序列化的結(jié)果
6.2 Gson性能優(yōu)化
// 1. 重用Gson實(shí)例
public class GsonHolder {
private static final Gson GSON = new GsonBuilder()
.setPrettyPrinting()
.create();
public static Gson getGson() {
return GSON;
}
}
// 2. 使用TypeAdapter進(jìn)行高性能序列化/反序列化
TypeAdapter<User> userAdapter = GsonHolder.getGson().getAdapter(User.class);
// 序列化到流
userAdapter.write(new JsonWriter(new FileWriter("user.json")), user);
// 從流反序列化
User user = userAdapter.read(new JsonReader(new FileReader("user.json")));
// 3. 避免使用toJsonTree再toJson,直接使用toJson
String json = GsonHolder.getGson().toJson(user);6.3 Jackson性能優(yōu)化
// 1. 重用ObjectMapper實(shí)例
public class ObjectMapperHolder {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
public static ObjectMapper getObjectMapper() {
return OBJECT_MAPPER;
}
}
// 2. 使用流式API處理大型JSON
// 序列化大型對(duì)象到文件
ObjectMapperHolder.getObjectMapper().writeValue(new File("large.json"), largeObject);
// 反序列化大型JSON
LargeObject largeObject = ObjectMapperHolder.getObjectMapper()
.readValue(new File("large.json"), LargeObject.class);
// 3. 使用JsonNode高效處理部分字段
JsonNode rootNode = ObjectMapperHolder.getObjectMapper().readTree(jsonString);
String neededField = rootNode.get("neededField").asText();
// 4. 使用TypeFactory預(yù)構(gòu)建復(fù)雜類型
JavaType listType = ObjectMapperHolder.getObjectMapper().getTypeFactory()
.constructCollectionType(List.class, User.class);6.4 Fastjson性能優(yōu)化
// 1. 使用TypeReference提高泛型反序列化性能
List<User> userList = JSON.parseObject(jsonList, new TypeReference<List<User>>() {});
// 2. 使用JSONB格式(Fastjson 2.0+)
byte[] bytes = JSONB.toJSONBBytes(user);
User parsedUser = JSONB.parseObject(bytes, User.class);
// 3. 自定義序列化過(guò)濾器提高性能
PropertyFilter propertyFilter = new PropertyFilter() {
@Override
public boolean apply(Object object, String name, Object value) {
// 只序列化需要的字段
return !"password".equals(name);
}
};
String json = JSON.toJSONString(user, propertyFilter);
// 4. 使用JSONReader處理大型JSON
JSONReader reader = new JSONReader(new StringReader(largeJson));
reader.startObject();
while (reader.hasNext()) {
String key = reader.readString();
if ("neededField".equals(key)) {
String value = reader.readString();
// 處理需要的字段
} else {
reader.skipValue();
}
}
reader.endObject();注意:性能優(yōu)化需要根據(jù)具體場(chǎng)景進(jìn)行測(cè)試和驗(yàn)證,不同的框架在不同場(chǎng)景下可能有不同的表現(xiàn)。建議使用JMH等基準(zhǔn)測(cè)試工具進(jìn)行性能對(duì)比。
7. 最佳實(shí)踐
7.1 選擇合適的框架
- 如果項(xiàng)目使用Spring框架,優(yōu)先考慮Jackson
- 如果對(duì)性能要求極高,可考慮Fastjson(注意安全問(wèn)題)
- 如果追求API簡(jiǎn)潔和易用性,可選擇Gson
7.2 代碼組織最佳實(shí)踐
// 示例:創(chuàng)建統(tǒng)一的JSON工具類
public class JsonUtils {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// 序列化方法
public static String toJson(Object obj) {
try {
return OBJECT_MAPPER.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON序列化失敗", e);
}
}
// 反序列化方法
public static <T> T fromJson(String json, Class<T> clazz) {
try {
return OBJECT_MAPPER.readValue(json, clazz);
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON反序列化失敗", e);
}
}
// 反序列化集合
public static <T> List<T> fromJsonList(String json, Class<T> clazz) {
try {
return OBJECT_MAPPER.readValue(
json,
OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, clazz)
);
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON列表反序列化失敗", e);
}
}
}7.3 錯(cuò)誤處理和異常管理
// 優(yōu)雅處理JSON解析異常
try {
User user = JsonUtils.fromJson(jsonString, User.class);
// 處理用戶對(duì)象
} catch (RuntimeException e) {
// 記錄詳細(xì)錯(cuò)誤信息
log.error("JSON解析失敗: {}", jsonString, e);
// 友好的錯(cuò)誤響應(yīng)
throw new BusinessException("數(shù)據(jù)格式錯(cuò)誤,請(qǐng)檢查輸入");
}
// 驗(yàn)證JSON格式
try {
ObjectMapperHolder.getObjectMapper().readTree(jsonString);
// JSON格式有效
} catch (Exception e) {
// JSON格式無(wú)效
throw new IllegalArgumentException("無(wú)效的JSON格式");
}7.4 安全處理
安全提示:處理外部JSON數(shù)據(jù)時(shí),務(wù)必注意安全問(wèn)題,特別是反序列化操作可能導(dǎo)致遠(yuǎn)程代碼執(zhí)行漏洞。
// Jackson安全配置
ObjectMapper mapper = new ObjectMapper();
// 禁用外部實(shí)體,防止XXE攻擊
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 限制反序列化的類
mapper.registerModule(new SimpleModule()
.addDeserializer(Object.class, new SafeObjectDeserializer()));
// Fastjson安全配置
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
// 使用白名單
ParserConfig.getGlobalInstance().addAccept("com.example.model.");
// Gson安全配置
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new SafeTypeAdapterFactory())
.create();7.5 處理日期時(shí)間
// Jackson日期時(shí)間處理
ObjectMapper mapper = new ObjectMapper();
// 配置日期格式
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// 支持Java 8日期時(shí)間API
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
// Gson日期時(shí)間處理
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeSerializer())
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeDeserializer())
.create();
// Fastjson日期時(shí)間處理
String json = JSON.toJSONString(dateObject,
SerializerFeature.WriteDateUseDateFormat);
// 自定義日期格式
JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
String formattedJson = JSON.toJSONString(dateObject,
SerializerFeature.WriteDateUseDateFormat);8. 常見(jiàn)問(wèn)題與解決方案
8.1 字段名不匹配
問(wèn)題:JSON中的字段名與Java類中的字段名不一致,導(dǎo)致反序列化失敗。
解決方案:
- Gson: 使用@SerializedName注解
- Jackson: 使用@JsonProperty注解
- Fastjson: 使用@JSONField注解
8.2 處理null值
問(wèn)題:JSON中包含null值,如何控制其序列化和反序列化行為。
解決方案:
- Gson: 使用GsonBuilder.serializeNulls()控制
- Jackson: 使用@JsonInclude(JsonInclude.Include.NON_NULL)注解或配置
- Fastjson: 使用SerializerFeature.WriteMapNullValue或@JSONField注解
8.3 循環(huán)引用問(wèn)題
問(wèn)題:對(duì)象之間存在循環(huán)引用,導(dǎo)致序列化時(shí)出現(xiàn)StackOverflowError。
解決方案:
- Gson: 默認(rèn)處理循環(huán)引用,但會(huì)生成$ref引用標(biāo)記
- Jackson: 使用@JsonManagedReference和@JsonBackReference注解
- Fastjson: 使用SerializerFeature.DisableCircularReferenceDetect禁用循環(huán)引用檢測(cè)
8.4 處理復(fù)雜嵌套結(jié)構(gòu)
問(wèn)題:JSON結(jié)構(gòu)復(fù)雜,難以直接映射到Java類。
解決方案:
- Gson: 使用JsonParser和JsonElement API
- Jackson: 使用JsonNode樹模型API
- Fastjson: 使用JSONObject和JSONArray API
8.5 性能問(wèn)題
問(wèn)題:處理大型JSON數(shù)據(jù)時(shí)性能不佳。
解決方案:
- 重用解析器實(shí)例
- 使用流式API而不是樹模型
- 避免不必要的字符串轉(zhuǎn)換
- 使用更高效的JSON庫(kù)(如需要高性能可考慮Fastjson)
9. 總結(jié)與建議
選擇建議
- Spring項(xiàng)目:優(yōu)先使用Jackson,與Spring框架集成良好
- 對(duì)性能要求極高的場(chǎng)景:考慮Fastjson,但需注意安全問(wèn)題
- 追求簡(jiǎn)潔API:Gson是不錯(cuò)的選擇
- 混合環(huán)境:可以根據(jù)不同模塊的需求選擇不同的框架
重要提示
- 始終使用最新穩(wěn)定版本的JSON庫(kù),以獲取安全補(bǔ)丁和性能改進(jìn)
- 在處理外部輸入的JSON數(shù)據(jù)時(shí),務(wù)必注意安全問(wèn)題
- 對(duì)于復(fù)雜的JSON處理需求,考慮封裝統(tǒng)一的工具類
- 在關(guān)鍵性能路徑上,進(jìn)行性能測(cè)試以選擇最優(yōu)方案
通過(guò)本文介紹的技巧和最佳實(shí)踐,相信您能夠在Java項(xiàng)目中更加高效、安全地處理JSON數(shù)據(jù)。選擇合適的工具,遵循最佳實(shí)踐,將使您的代碼更加健壯和可維護(hù)。
到此這篇關(guān)于Java處理JSON編程實(shí)用技巧和性能優(yōu)化的文章就介紹到這了,更多相關(guān)Java處理JSON技巧內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA java關(guān)閉某些代碼檢查提示W(wǎng)arning實(shí)現(xiàn)方式
文章內(nèi)容涉及編程中兩種常見(jiàn)警告:Methodisneverused(未使用方法)和Uncheckedcast(未檢查類型轉(zhuǎn)換),提示需檢查代碼邏輯及類型安全處理2025-09-09
Spring調(diào)度框架EnableScheduling&Scheduled源碼解析
這篇文章主要介紹了Spring調(diào)度框架EnableScheduling&Scheduled源碼解析,@EnableScheduling&Scheduled定時(shí)調(diào)度框架,本著不僅知其然還要知其所以然的指導(dǎo)思想,下面對(duì)該調(diào)度框架進(jìn)行源碼解析,以便更好的理解其執(zhí)行過(guò)程,需要的朋友可以參考下2024-01-01
Springboot日志開(kāi)啟SLF4J過(guò)程解析
這篇文章主要介紹了Springboot日志開(kāi)啟SLF4J過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
java動(dòng)態(tài)構(gòu)建數(shù)據(jù)庫(kù)復(fù)雜查詢教程
這篇文章主要介紹了java動(dòng)態(tài)構(gòu)建數(shù)據(jù)庫(kù)復(fù)雜查詢的實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-11-11
IDEA2022 提示更新 TKK失敗請(qǐng)檢查網(wǎng)絡(luò)連接的問(wèn)題
這篇文章主要介紹了IDEA2022 提示:更新 TKK 失敗,請(qǐng)檢查網(wǎng)絡(luò)連接,本文給大家分享解決方案,對(duì)idea2022提示更新TKK失敗感興趣的朋友跟隨小編一起看看吧2022-11-11
springboot 使用poi進(jìn)行數(shù)據(jù)的導(dǎo)出過(guò)程詳解
這篇文章主要介紹了springboot 使用poi進(jìn)行數(shù)據(jù)的導(dǎo)出過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09

