亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java實(shí)現(xiàn)讀寫(xiě)json文件的示例詳解

 更新時(shí)間:2025年05月27日 09:22:54   作者:Katie。  
隨著現(xiàn)代應(yīng)用對(duì)數(shù)據(jù)交換和配置管理需求的增加,JSON(JavaScript Object Notation)已成為最流行的數(shù)據(jù)格式之一,本文將為大家全面展示 Java 讀寫(xiě) JSON 文件的端到端流程,需要的小伙伴可以了解下

1. 項(xiàng)目背景詳細(xì)介紹

隨著現(xiàn)代應(yīng)用對(duì)數(shù)據(jù)交換和配置管理需求的增加,JSON(JavaScript Object Notation)已成為最流行的數(shù)據(jù)格式之一。其結(jié)構(gòu)清晰、可讀性高、跨語(yǔ)言支持廣泛,適用于配置文件、日志輸出、前后端數(shù)據(jù)交互等多種場(chǎng)景。Java 平臺(tái)上,雖然原生沒(méi)有提供對(duì) JSON 的直接支持,但通過(guò)第三方庫(kù)(如 Jackson、Gson、Fastjson 等),可以非常便捷地實(shí)現(xiàn) JSON 文件的讀寫(xiě)和對(duì)象映射。

本項(xiàng)目旨在通過(guò)一個(gè)簡(jiǎn)單的“用戶配置”示例,全面展示 Java 讀寫(xiě) JSON 文件的端到端流程,包括:定義數(shù)據(jù)模型、使用 Jackson 庫(kù)讀寫(xiě) JSON 文件、異常處理與單元測(cè)試等。文章適合 Java 初學(xué)者,以及希望掌握 JSON 操作的開(kāi)發(fā)者,既可作為博客,也可用于課堂教學(xué)。

2. 項(xiàng)目需求詳細(xì)介紹

2.1 功能需求

1.讀取 JSON 文件

  • 從指定路徑加載 JSON 文件;
  • 將 JSON 內(nèi)容解析為 Java 對(duì)象。

2.寫(xiě)入 JSON 文件

  • 將 Java 對(duì)象序列化為 JSON 字符串;
  • 寫(xiě)入指定路徑的文件,支持覆蓋與追加兩種模式。

3.數(shù)據(jù)模型定義

  • 定義 UserConfig 類,包含多種字段類型(字符串、整數(shù)、列表、嵌套對(duì)象等);
  • 通過(guò)注解或配置,實(shí)現(xiàn)字段與 JSON 鍵的靈活映射。

4.異常與校驗(yàn)

  • 讀取異常(文件未找到、格式錯(cuò)誤)應(yīng)捕獲并給出友好提示;
  • 寫(xiě)入時(shí)處理 I/O 錯(cuò)誤與磁盤空間不足情況;
  • 對(duì)必需字段進(jìn)行非空校驗(yàn)。

5.單元測(cè)試與示例

  • 提供 JUnit 測(cè)試,驗(yàn)證讀寫(xiě)邏輯正確性;
  • 包含示例主程序,演示整個(gè)流程。

2.2 性能與非功能需求

性能:處理 1 萬(wàn)條配置記錄的 JSON 文件,讀取/寫(xiě)入時(shí)間 < 200ms;

可維護(hù)性:模塊化設(shè)計(jì),代碼清晰注釋詳盡;

易用性:API 簡(jiǎn)單直觀,README 指南完整;

兼容性:支持 Java 8 及以上版本;

3. 相關(guān)技術(shù)詳細(xì)介紹

1.Jackson

  • 最流行的 Java JSON 處理庫(kù);
  • 提供 ObjectMapper,支持注解方式(@JsonProperty、@JsonInclude 等);
  • 支持流式(Streaming)、樹(shù)模型(Tree Model)、數(shù)據(jù)綁定(Data Binding)多種用法。

2.Gson / Fastjson 簡(jiǎn)述

  • Gson:Google 開(kāi)源,API 簡(jiǎn)潔,但對(duì)泛型支持需 TypeToken;
  • Fastjson:阿里巴巴開(kāi)源,性能較好,但安全性需注意。

3.Java I/O 與 NIO

  • 使用 Files、Paths 等簡(jiǎn)單 API;
  • 對(duì)大文件可采用 NIO 通道和緩沖區(qū)優(yōu)化。

4.JUnit 5

  • 單元測(cè)試框架,用于驗(yàn)證 JSON 讀寫(xiě)功能;
  • 支持?jǐn)嘌?、異常測(cè)試、臨時(shí)文件夾規(guī)則等。

4. 實(shí)現(xiàn)思路詳細(xì)介紹

1.項(xiàng)目結(jié)構(gòu)

json-demo/
├─ src/
│  ├─ main/
│  │  ├─ java/com/example/json/
│  │  │  ├─ model/UserConfig.java
│  │  │  ├─ util/JsonUtils.java
│  │  │  └─ App.java
│  └─ test/
│     └─ java/com/example/json/
│        └─ JsonUtilsTest.java
└─ pom.xml

2.核心流程

  • 定義 UserConfig:包括 id、name、email、roles(列表)、profile(嵌套對(duì)象)等字段;
  • 在 JsonUtils 中封裝 readJson(path, Class<T>) 與 writeJson(path, obj, boolean append) 方法;
  • 在 App 中調(diào)用上述工具方法,實(shí)現(xiàn)讀取 → 修改 → 寫(xiě)入的示例流程;
  • 使用 JUnit 測(cè)試讀寫(xiě)結(jié)果與異常處理。

3.字段映射與注解

  • 使用 @JsonProperty("user_id") 映射字段名;
  • 配置 ObjectMapper 忽略未知屬性、忽略空字段。

4.大文件性能優(yōu)化

  • 對(duì)于超大 JSON 文件(>100MB),采用 Jackson Streaming API:JsonParser / JsonGenerator;
  • 結(jié)合 BufferedInputStream 與 BufferedOutputStream,減少 I/O 調(diào)用次數(shù)。

5.異常處理策略

  • 捕獲 IOException、JsonProcessingException,包裝為自定義 JsonException;
  • 在調(diào)用處進(jìn)行區(qū)分處理:提示用戶、重試或退出。

5. 完整實(shí)現(xiàn)代碼

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>json-demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <dependencies>
    <!-- Jackson 核心 -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.15.2</version>
    </dependency>
    <!-- JUnit 5 -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.9.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M7</version>
      </plugin>
    </plugins>
  </build>
</project>

java代碼

// ========== src/main/java/com/example/json/model/UserConfig.java ==========
package com.example.json.model;
 
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.Map;
 
/**
 * 用戶配置模型
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserConfig {
    @JsonProperty("user_id")
    private int id;
 
    private String name;
    private String email;
 
    private List<String> roles;
 
    private Map<String, Object> profile;
 
    // 構(gòu)造方法、getter、setter 省略
}
 
// ========== src/main/java/com/example/json/util/JsonUtils.java ==========
package com.example.json.util;
 
import com.example.json.model.UserConfig;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
 
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
 
/**
 * JSON 讀寫(xiě)工具類
 */
public class JsonUtils {
 
    private static final ObjectMapper MAPPER = new ObjectMapper();
    static {
        MAPPER.configure(SerializationFeature.INDENT_OUTPUT, true);
        MAPPER.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, true);
    }
 
    /**
     * 讀取 JSON 文件到指定類型對(duì)象
     */
    public static <T> T readJson(String filePath, Class<T> clazz) throws JsonException {
        try {
            return MAPPER.readValue(new File(filePath), clazz);
        } catch (IOException e) {
            throw new JsonException("讀取 JSON 文件失敗: " + filePath, e);
        }
    }
 
    /**
     * 寫(xiě)入對(duì)象為 JSON 文件
     * @param append 是否追加,true 時(shí)在文件末尾追加;false 覆蓋寫(xiě)入
     */
    public static void writeJson(String filePath, Object obj, boolean append) throws JsonException {
        try (Writer writer = new BufferedWriter(new FileWriter(filePath, append))) {
            MAPPER.writeValue(writer, obj);
        } catch (IOException e) {
            throw new JsonException("寫(xiě)入 JSON 文件失敗: " + filePath, e);
        }
    }
 
    /**
     * 大文件流式寫(xiě)入示例
     */
    public static void writeJsonStream(String filePath, List<UserConfig> list) throws JsonException {
        JsonFactory factory = new JsonFactory();
        try (JsonGenerator gen = factory.createGenerator(new File(filePath), JsonFactory.Feature.WRITE_BIGDECIMAL_AS_PLAIN)) {
            gen.writeStartArray();
            for (UserConfig cfg : list) {
                MAPPER.writeValue(gen, cfg);
            }
            gen.writeEndArray();
        } catch (IOException e) {
            throw new JsonException("流式寫(xiě)入 JSON 失敗: " + filePath, e);
        }
    }
}
 
// ========== src/main/java/com/example/json/util/JsonException.java ==========
package com.example.json.util;
 
/**
 * JSON 操作異常
 */
public class JsonException extends Exception {
    public JsonException(String message, Throwable cause) {
        super(message, cause);
    }
}
 
// ========== src/main/java/com/example/json/App.java ==========
package com.example.json;
 
import com.example.json.model.UserConfig;
import com.example.json.util.JsonUtils;
import com.example.json.util.JsonException;
 
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
 
public class App {
    public static void main(String[] args) {
        String path = "data/user_config.json";
 
        try {
            // 1. 讀取現(xiàn)有配置
            UserConfig cfg = JsonUtils.readJson(path, UserConfig.class);
            System.out.println("讀取配置: " + cfg);
 
            // 2. 修改并寫(xiě)回
            cfg.setRoles(Arrays.asList("admin", "user"));
            Map<String,Object> profile = new HashMap<>();
            profile.put("age", 30);
            profile.put("address", "北京");
            cfg.setProfile(profile);
            JsonUtils.writeJson(path, cfg, false);
            System.out.println("寫(xiě)入配置完成");
 
        } catch (JsonException e) {
            e.printStackTrace();
        }
    }
}
 
// ========== src/test/java/com/example/json/JsonUtilsTest.java ==========
package com.example.json;
 
import com.example.json.model.UserConfig;
import com.example.json.util.JsonUtils;
import com.example.json.util.JsonException;
import org.junit.jupiter.api.*;
import java.nio.file.*;
 
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class JsonUtilsTest {
 
    private final String testFile = "target/test_config.json";
 
    @BeforeAll
    void init() throws Exception {
        Files.createDirectories(Paths.get("target"));
    }
 
    @Test
    void testReadWrite() throws JsonException {
        UserConfig cfg = new UserConfig();
        cfg.setId(100);
        cfg.setName("測(cè)試");
        JsonUtils.writeJson(testFile, cfg, false);
 
        UserConfig read = JsonUtils.readJson(testFile, UserConfig.class);
        Assertions.assertEquals(100, read.getId());
        Assertions.assertEquals("測(cè)試", read.getName());
    }
 
    @Test
    void testReadNotFound() {
        Assertions.assertThrows(JsonException.class, () -> {
            JsonUtils.readJson("nonexistent.json", UserConfig.class);
        });
    }
}

6. 代碼詳細(xì)解讀

UserConfig:使用 Jackson 注解映射 JSON 字段,包含基本類型、列表、嵌套 Map。

JsonUtils.readJson:封裝 ObjectMapper.readValue,處理文件 I/O 與映射異常。

JsonUtils.writeJson:使用 BufferedWriter 控制覆蓋或追加模式,將對(duì)象序列化為格式化 JSON。

JsonUtils.writeJsonStream:演示流式寫(xiě)入大文件,逐條序列化以降低內(nèi)存占用。

JsonException:統(tǒng)一包裝 JSON 相關(guān)異常,調(diào)用方可根據(jù)類型分別處理。

App:示例應(yīng)用,展示讀取、修改、寫(xiě)回的完整流程。

JsonUtilsTest:JUnit 5 單元測(cè)試,驗(yàn)證正常讀寫(xiě)、異常場(chǎng)景,確保工具類可靠。

7. 項(xiàng)目詳細(xì)總結(jié)

本項(xiàng)目通過(guò) Jackson 庫(kù)與標(biāo)準(zhǔn) Java I/O,完整實(shí)現(xiàn)了對(duì) JSON 文件的讀寫(xiě),包括簡(jiǎn)單場(chǎng)景與大文件流式場(chǎng)景;通過(guò)模塊化工具類、統(tǒng)一異常處理和單元測(cè)試,保證了代碼的可維護(hù)性與可靠性。項(xiàng)目結(jié)構(gòu)清晰,注釋詳盡,適合快速上手和二次擴(kuò)展。

8. 項(xiàng)目常見(jiàn)問(wèn)題及解答

JSON 文件包含未知字段時(shí)如何處理?

默認(rèn) Jackson 會(huì)拋出異常,可通過(guò) MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 忽略未知字段。

追加模式寫(xiě)入的 JSON 格式如何保持合法?

追加時(shí)需控制文件內(nèi)容格式,可先讀入 List,添加后整體寫(xiě)回,避免手動(dòng)追加導(dǎo)致格式錯(cuò)誤。

大文件讀寫(xiě)導(dǎo)致 OOM?

對(duì)于超大數(shù)組,應(yīng)使用 Jackson Streaming API,逐條讀寫(xiě),避免一次性加載。

如何在 Spring Boot 中集成?

將 JsonUtils 封裝為 @Component,并注入自定義配置的 ObjectMapper 即可。

多線程并發(fā)讀寫(xiě)如何保證安全?

寫(xiě)操作時(shí)可在工具類中加入 synchronized,或由調(diào)用方通過(guò)外部鎖保證;讀操作一般是無(wú)狀態(tài)的,可以并發(fā)執(zhí)行。

9. 擴(kuò)展方向與性能優(yōu)化

支持 YAML / XML:添加 SnakeYAML、Jackson XML 模塊,實(shí)現(xiàn)多格式互轉(zhuǎn)。

異步 I/O:結(jié)合 NIO AsynchronousFileChannel,異步讀寫(xiě)提升吞吐。

緩存機(jī)制:對(duì)頻繁讀取的配置引入內(nèi)存緩存,定時(shí)刷新或文件變更監(jiān)聽(tīng)。

Schema 校驗(yàn):引入 JSON Schema,對(duì)輸入輸出進(jìn)行嚴(yán)格校驗(yàn),保證數(shù)據(jù)一致性。

分布式配置:集成 Apollo、Spring Cloud Config,將 JSON 文件遷移至配置中心。

大文件并發(fā)處理:結(jié)合多線程分片讀取/寫(xiě)入,并行序列化。

到此這篇關(guān)于java實(shí)現(xiàn)讀寫(xiě)json文件的示例詳解的文章就介紹到這了,更多相關(guān)java讀寫(xiě)json內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文探索Java文件讀寫(xiě)更高效方式

    一文探索Java文件讀寫(xiě)更高效方式

    這篇文章主要介紹了一文探索Java文件讀寫(xiě)更高效方式,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值需要的小伙伴可以參考一下
    2022-07-07
  • SpringBoot整合ELK做日志超完整詳細(xì)教程

    SpringBoot整合ELK做日志超完整詳細(xì)教程

    本文詳細(xì)介紹了如何在springboot中快速接入ELK的過(guò)程,ELK可以說(shuō)在實(shí)際項(xiàng)目中具有很好的適用價(jià)值,不管是小項(xiàng)目,還是中大型項(xiàng)目,都具備普適參考性,值得深入了解和學(xué)習(xí),感興趣的朋友一起看看吧
    2024-01-01
  • Mybatis分解式查詢使用方法

    Mybatis分解式查詢使用方法

    這篇文章主要介紹了Mybatis分解式查詢使用方法,分解式查詢就是將一條Sql語(yǔ)句拆分成多條。在 MyBatis 多表查詢中,使用連接查詢時(shí)一個(gè) Sql 語(yǔ)句就可以查詢出所有的數(shù)據(jù)
    2023-04-04
  • IDEA創(chuàng)建父項(xiàng)目和子項(xiàng)目的實(shí)現(xiàn)步驟

    IDEA創(chuàng)建父項(xiàng)目和子項(xiàng)目的實(shí)現(xiàn)步驟

    本文主要介紹了IDEA創(chuàng)建父項(xiàng)目和子項(xiàng)目的實(shí)現(xiàn)步驟,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • Java超詳細(xì)介紹封裝與訪問(wèn)控制修符

    Java超詳細(xì)介紹封裝與訪問(wèn)控制修符

    封裝是一個(gè)非常廣泛的概念,小到一個(gè)屬性的封裝,大到一個(gè)框架或者一個(gè)項(xiàng)目的封裝,文中通過(guò)實(shí)例代碼將詳細(xì)介紹封裝與訪問(wèn)控制修飾符
    2022-05-05
  • 簡(jiǎn)單學(xué)習(xí)Java API 設(shè)計(jì)實(shí)踐

    簡(jiǎn)單學(xué)習(xí)Java API 設(shè)計(jì)實(shí)踐

    API(Application Programming Interface,應(yīng)用程序編程接口)是一些預(yù)先定義的函數(shù),目的是提供應(yīng)用程序與開(kāi)發(fā)人員基于某軟件或硬件的以訪問(wèn)一組例程的能力,而又無(wú)需訪問(wèn)源碼,或理解內(nèi)部工作機(jī)制的細(xì)節(jié)。需要的可以了解一下
    2019-06-06
  • 詳解Java基礎(chǔ)之封裝

    詳解Java基礎(chǔ)之封裝

    這篇文章主要為大家介紹了Java基礎(chǔ)之封裝,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • Java8時(shí)間接口LocalDateTime詳細(xì)用法

    Java8時(shí)間接口LocalDateTime詳細(xì)用法

    最近看別人項(xiàng)目源碼,發(fā)現(xiàn)Java8新的日期時(shí)間API很方便強(qiáng)大,所以整理了這篇文章,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-05-05
  • SpringBoot自定義FailureAnalyzer過(guò)程解析

    SpringBoot自定義FailureAnalyzer過(guò)程解析

    這篇文章主要介紹了SpringBoot自定義FailureAnalyzer,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java對(duì)象初始化過(guò)程代碼塊和構(gòu)造器的調(diào)用順序

    Java對(duì)象初始化過(guò)程代碼塊和構(gòu)造器的調(diào)用順序

    這篇文章主要介紹了Java對(duì)象初始化過(guò)程代碼塊和構(gòu)造器的調(diào)用順序,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08

最新評(píng)論