1. 序章

この短いチュートリアルでは、Jacksonを使用してJSONをCSVに、またはその逆に変換する方法を説明します。

org.jsonCDLクラスなど、利用可能な代替ライブラリがありますが、ここではジャクソンライブラリに焦点を当てます。

データ構造の例を確認した後、 ObjectMapper とCSVMapperの組み合わせを使用して、JSONとCSVの間で変換します。

2. 依存関係

JacksonCSVデータフォーマッタの依存関係を追加しましょう。

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

この依存関係の最新バージョンは、 MavenCentralでいつでも見つけることができます。

コアJacksonデータバインドの依存関係も追加します。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
</dependency>

この場合も、この依存関係の最新バージョンは MavenCentralにあります。

3. データ構造

JSONドキュメントをCSVに再フォーマットする前に、データモデルが2つのフォーマット間でどの程度適切にマッピングされるかを検討する必要があります。

まず、さまざまな形式でサポートされているデータについて考えてみましょう。

  • JSONを使用して、配列やネストされたオブジェクトを含むものなど、さまざまなオブジェクト構造を表現します
  • CSVを使用してオブジェクトのリストからのデータを表し、リストの各オブジェクトが新しい行に表示されます

これは、JSONドキュメントにオブジェクトの配列がある場合、各オブジェクトをCSVファイルの新しい行に再フォーマットできることを意味します。 したがって、例として、注文の次のアイテムのリストを含むJSONドキュメントを使用してみましょう。

[ {
  "item" : "No. 9 Sprockets",
  "quantity" : 12,
  "unitPrice" : 1.23
}, {
  "item" : "Widget (10mm)",
  "quantity" : 4,
  "unitPrice" : 3.45
} ]

JSONドキュメントのフィールド名を列ヘッダーとして使用し、次のCSVファイルに再フォーマットします。

item,quantity,unitPrice
"No. 9 Sprockets",12,1.23
"Widget (10mm)",4,3.45

4. JSONの読み取りとCSVの書き込み

まず、Jacksonの ObjectMapper を使用して、サンプルのJSONドキュメントをJsonNodeオブジェクトのツリーに読み込みます。

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

次に、CsvSchemaを作成しましょう。 これにより、CSVファイルの列ヘッダー、タイプ、および列の順序が決まります。 これを行うには、 CsvSchema Builder を作成し、JSONフィールド名と一致するように列ヘッダーを設定します。

Builder csvSchemaBuilder = CsvSchema.builder();
JsonNode firstObject = jsonTree.elements().next();
firstObject.fieldNames().forEachRemaining(fieldName -> {csvSchemaBuilder.addColumn(fieldName);} );
CsvSchema csvSchema = csvSchemaBuilder.build().withHeader();

次に、CsvSchemaを使用してCsvMapperを作成し、最後にjsonTreeをCSVファイルに書き込みます

CsvMapper csvMapper = new CsvMapper();
csvMapper.writerFor(JsonNode.class)
  .with(csvSchema)
  .writeValue(new File("src/main/resources/orderLines.csv"), jsonTree);

このサンプルコードを実行すると、サンプルのJSONドキュメントが期待されるCSVファイルに変換されます。

5. CSVの読み取りとJSONの書き込み

次に、Jacksonの CsvMapper を使用して、CSVファイルをOrderLineオブジェクトのListに読み込みます。 これを行うには、最初にOrderLineクラスを単純なPOJOとして作成します。

public class OrderLine {
    private String item;
    private int quantity;
    private BigDecimal unitPrice;
 
    // Constructors, Getters, Setters and toString
}

CSVファイルの列ヘッダーを使用してCsvSchemaを定義します。 次に、 CsvMapperを使用して、CSVからOrderLineオブジェクトのMappingIteratorにデータを読み込みます。

CsvSchema orderLineSchema = CsvSchema.emptySchema().withHeader();
CsvMapper csvMapper = new CsvMapper();
MappingIterator<OrderLine> orderLines = csvMapper.readerFor(OrderLine.class)
  .with(orderLineSchema)
  .readValues(new File("src/main/resources/orderLines.csv"));

次に、 MappingIterator を使用して、OrderLineオブジェクトのListを取得します。 次に、Jacksonの ObjectMapper を使用して、リストをJSONドキュメントとして書き出します。

new ObjectMapper()
  .configure(SerializationFeature.INDENT_OUTPUT, true)
  .writeValue(new File("src/main/resources/orderLinesFromCsv.json"), orderLines.readAll());

このサンプルコードを実行すると、サンプルのCSVファイルが期待されるJSONドキュメントに変換されます。

6. CSVファイル形式の構成

ジャクソンの注釈のいくつかを使用して、CSVファイルの形式を調整してみましょう。 ‘item’列見出しを‘name’に変更し、‘quantity’列見出しを‘count’に変更します。 ‘unitPrice’ 列を削除し、‘count’を最初の列にします。

したがって、予想されるCSVファイルは次のようになります。

count,name
12,"No. 9 Sprockets"
4,"Widget (10mm)"

CSVファイルに必要な形式を定義するための新しい抽象クラスを作成します。

@JsonPropertyOrder({
    "count",
    "name"
})
public abstract class OrderLineForCsv {
    
    @JsonProperty("name")
    private String item; 
    
    @JsonProperty("count")
    private int quantity; 
    
    @JsonIgnore
    private BigDecimal unitPrice;

}

次に、 OrderLineForCsv クラスを使用して、CsvSchemaを作成します。

CsvMapper csvMapper = new CsvMapper();
CsvSchema csvSchema = csvMapper
  .schemaFor(OrderLineForCsv.class)
  .withHeader(); 

また、OrderLineForCsvをJacksonMixinとして使用します。 これにより、Jacksonは、 OrderLine オブジェクトを処理するときに、OrderLineForCsvクラスに追加した注釈を使用するように指示されます。

csvMapper.addMixIn(OrderLine.class, OrderLineForCsv.class); 

最後に、ObjectMapperを使用してJSONドキュメントをOrderLine配列に読み込み、csvMapperを使用してこれをCSVファイルに書き込みます。

OrderLine[] orderLines = new ObjectMapper()
    .readValue(new File("src/main/resources/orderLines.json"), OrderLine[].class);
    
csvMapper.writerFor(OrderLine[].class)
    .with(csvSchema)
    .writeValue(new File("src/main/resources/orderLinesReformated.csv"), orderLines);

このサンプルコードを実行すると、サンプルのJSONドキュメントが期待されるCSVファイルに変換されます。

7. 結論

このクイックチュートリアルでは、Jacksonデータ形式ライブラリを使用してCSVファイルを読み書きする方法を学びました。 また、データを希望どおりに表示するのに役立ついくつかの構成オプションについても検討しました。

いつものように、コードはGitHubにあります。