Chuyển đổi JSON qua CSV sử dụng thư viện Jackson

146

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

Thư viện Jackson giúp cho chúng ta có thể chuyển đổi data dưới dạng JSON sang các định dạng data khác nhau và ngược lại. Trong bài viết này, mình hướng dẫn các bạn cách chuyển đổi data từ JSON sang CSV như thế nào các bạn nhé!

  Cách tạo REST API với JSON Server
  Ghi chú file package.json của node module

Xem thêm các việc làm JSON hấp dẫn trên TopDev

Đầu tiên, mình sẽ tạo mới một Maven project:

với Jackson Dataformat CSV dependency như sau:

<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
<version>2.13.0</version>
</dependency>

Để làm ví dụ, mình sẽ chuyển đổi chuỗi JSON sau sang tập tin CSV:

{
"name" : "Khanh",
"code" : 99,
"date" : "04-07-2017",
"gotMarried": true
}

Để bắt đầu, mình sẽ tạo mới một Application class với main() method như sau:

package com.huongdanjava.jackson;

public class Application {

public static void main(String[] args) {

}
}

Đầu tiên, các bạn có thể sử dụng phương thức readTree() của đối tượng ObjectMapper của Jackson để đọc nội dung JSON mà các bạn cần chuyển đổi. 

Có nhiều phương thức overload readTree() hỗ trợ cho các bạn làm điều này:

Các bạn có thể đọc nội dung JSON từ file, từ chuỗi, từ byte,… Tuỳ theo bài toán mà các bạn hãy sử dụng các phương thức overload của readTree() cho hợp lý nhé. Ở đây, mình sẽ lưu nội dung JSON trên vào tập tin data.json ở thư mục src/main/resources để làm ví dụ:

JsonNode jsonNode = new ObjectMapper().readTree(new File("src/main/resources/data.json"));

Nội dung JSON này sẽ được lưu vào đối tượng JsonNode như các bạn thấy!

Tiếp theo, chúng ta sẽ sử dụng đối tượng CsvSchema Builder để định nghĩa các column của tập tin CSV.

Cho ví dụ của mình thì code sẽ như sau:

CsvSchema.Builder builder = CsvSchema.builder();
jsonNode.elements().next().fieldNames().forEachRemaining(f -> builder.addColumn(f));

Đoạn code trên là chúng ta đang lấy tất cả các key trong JSON data, bao gồm name, code, date, gotMarried trong ví dụ của mình, để định nghĩa là column trong tập tin CSV các bạn nhé!

Các bạn cũng có thể chỉ định những data nào, tương ứng với key nào trong JSON data được convert qua tập tin CSV bằng cách định nghĩa CsvSchema Builder như sau:

CsvSchema.Builder builder = CsvSchema.builder()
.addColumn("name")
.addColumn("code")
.addColumn("date");

Với đoạn code này thì ví dụ của mình chỉ có data của column name, code và date được convert mà thôi. Mình sẽ sử dụng code này trong bài viết này để làm ví dụ.

Sau khi đã có CsvSchema Builder xong thì các bạn có thể lấy đối tượng CsvSchema như sau:

CsvSchema csvSchema = builder.build().withHeader();

Bây giờ thì chúng ta có thể sử dụng CsvMapper để chuyển đổi JSON data sang CSV data rồi:

CsvMapper csvMapper = new CsvMapper();
csvMapper.configure(Feature.IGNORE_UNKNOWN, true);
csvMapper.writerFor(JsonNode.class)
.with(csvSchema)
.writeValue(new File("src/main/resources/data.cvs"), jsonNode);

Bởi vì mình đang định nghĩa các column manually, nên sẽ có những column mà CsvMapper không aware được khi làm việc chuyển đổi. Do đó, mình cần cấu hình để nó ignore những column đó đi.

Trong ví dụ này, mình lưu tập tin output data.csv ở thư mục src/main/resources.

Toàn bộ code của ví dụ như sau:

package com.huongdanjava.jackson;

import com.fasterxml.jackson.core.JsonGenerator.Feature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import java.io.File;
import java.io.IOException;

public class Application {

public static void main(String[] args) throws IOException {
JsonNode jsonNode = new ObjectMapper().readTree(new File("src/main/resources/data.json"));

CsvSchema.Builder builder = CsvSchema.builder()
.addColumn("name")
.addColumn("code")
.addColumn("date");

CsvSchema csvSchema = builder.build().withHeader();

CsvMapper csvMapper = new CsvMapper();
csvMapper.configure(Feature.IGNORE_UNKNOWN, true);
csvMapper.writerFor(JsonNode.class)
.with(csvSchema)
.writeValue(new File("src/main/resources/data.csv"), jsonNode);
}
}

Kết quả khi chạy chương trình như sau:

Jackson sẽ không làm việc được với những kiểu dữ liệu nested JSON các bạn nhé.

Ví dụ như nếu các bạn có chuỗi JSON sau:

{
"name" : "Khanh",
"code" : 99,
"date" : "04-07-2017",
"gotMarried": true,
"group" : [
"ABC", "XYZ"
],
"class" : {
"name" : "A",
"code" : 123
}
}

thì khi code, các bạn cần định nghĩa manually tên các column để loại bỏ những nested JSON này ra các bạn nhé!

Bài viết gốc được đăng tải tại huongdanjava.com

Có thể bạn quan tâm:

Xem thêm việc làm CNTT hấp dẫn trên TopDev