3. 書式の指定方法

数値や日時型などに対して書式を指定する方法を説明します。

独自のクラスタイプに対応しても、専用クラスを用意することで対応できます。

3.1. 書式指定用の既存のアノテーション

表 - 3.1.1 書式を指定する既存のアノテーション

アノテーション

概要

参照

@CsvBooleanFormat

ブール型に対する書式を指定します。

JavaDoc

@CsvNumberFormat

数値型に対する書式を指定します。

JavaDoc

@CsvDateTimeFormat

日時型に対する書式を指定します。

JavaDoc

@CsvEnumFormat

列挙型に対する書式を指定します。

JavaDoc

3.1.1. @CsvBooleanFormat

クラスタイプが「boolean/Boolean」のマッピング規則を定義する際に使用します。

通常の「true、false」以外に、「○、×」などでのマッピングが可能となります。

注釈

プリミティブ型に対して読み込む際に、CSVのカラムの値が空の場合、 false が設定されます。 初期値を変更したい場合は、アノテーション @CsvDefaultValue [JavaDoc]を使用してください。

3.1.1.1. 読み込み時の値の指定

属性 readForTruereadForFalse で、読み込み時のtrueまたはfalseと判定する候補の値を指定します。

  • 属性readForTrueとreadForFalseの値に重複がある場合、readForTrueの定義が優先されまます。

  • 属性readForTrueを指定しない場合、デフォルトで「"true", "1", "yes", "on", "y", "t"」が設定されます。

  • 属性readForFalseを指定しない場合、デフォルトで「"false", "0", "no", "off", "f", "n"」が設定されます。

  • 属性 ignoreCase の値をtrueにすると、読み込み時に大文字・小文字の区別なく候補の値と比較します。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvBooleanFormat;
 4
 5@CsvBean
 6public class SampleCsv {
 7
 8    // boolean型の読み込み時のtrueとfalseの値の変換規則を指定します。
 9    @CsvColumn(number=1, label="ステータス")
10    @CsvBooleanFormat(
11            readForTrue={"○", "有効", "レ"},
12            readForFalse={"×", "無効", "-", ""})
13    private boolean availaled;
14
15    // 読み込み時の大文字・小文字の区別を行わない
16    @CsvColumn(number=2, label="チェック")
17    @CsvBooleanFormat(
18          readForTrue={"OK"},
19          readForFalse={"NO"},
20          ignoreCase=true)
21    private Boolean checked;
22
23    // getter/setterは省略
24}

3.1.1.2. 書き込み時の値の指定

属性 writeAsTruewriteAsFalse で、書き込み時のtrueまたはfalse値に該当する文字を指定します。

  • 属性writeAsTrueを指定しない場合は、デフォルトで"true"が設定され、セルのタイプもブール型になります。

  • 属性writeAsFalseを指定しない場合は、デフォルトで"false"が設定され、セルのタイプもブール型になります。

  • 読み込みと書き込みの両方を行う場合、属性readForTrueとreadForFalseの値に属性writeAsTrueとwriteAsFalseの値を含める必要があります。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvBooleanFormat;
 4
 5@CsvBean
 6public class SampleCsv {
 7
 8    // boolean型の書き込み時のtrueとfalseの値の変換規則を指定します。
 9    @CsvColumn(number=1, label="ステータス")
10    @CsvBooleanFormat(
11            readForTrue={"○", "有効", "レ"}, // 読み書きの両方を行う場合、書き込む値を含める必要がある。
12            readForFalse={"×", "無効", "-", ""},
13            writeAsTrue="○",
14            writeAsFalse="×")
15    )
16    private boolean availaled;
17
18    // getter/setterは省略
19}

3.1.1.3. 読み込み時の値のパースに失敗した際の処理

読み込み時にtrueまたはfalseに変換できない場合、例外 SuperCsvValidationException が発生します。

  • 属性 failToFalse をtrueに設定することで、変換できない場合に強制的に値をfalseとして読み込み、例外を発生しなくできます。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3
 4import com.github.mygreen.supercsv.annotation.format.CsvBooleanFormat;
 5
 6public class SampleCsv {
 7
 8    // 読み込み時のtrue,falseに定義していない値を読み込んだときにfalseとして読み込む。
 9    @CsvColumn(number=1, label="ステータス")
10    @CsvBooleanFormat(
11            readForTrue={"○", "有効", "レ"},
12            readForFalse={"×", "無効", "-", ""},
13            failToFalse=true)
14    private boolean availaled;
15
16    // setter/getterは省略
17}

3.1.1.4. 読み込み時の値のパースに失敗した際のメッセージ

読み込み時に値のパースに失敗した時に独自のメッセージとして、属性 message で指定することができます。

メッセージ中は、JEXL による式言語を使うことができ、 予め登録されている変数を用いて、メッセージ内容を独自にカスタマイズすることができます。 詳細は、値の検証時のメッセージ を参照してください。

メッセージ中で利用可能な変数は、JavaDoc を参照してください。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvBooleanFormat;
 4
 5@CsvBean
 6public class SampleCsv {
 7
 8    @CsvColumn(number=1, label="ステータス")
 9    @CsvBooleanFormat(message="[{rowNumber}行, {columnNumber}列] : 項目「{label}」の値({validatedValue})は、trueの値「${f:join(trueValues, ', ')}」、またはfalseの値「${f:join(falseValues, ', ')}」の何れかの値で設定してください。"
10    private boolean availaled;
11
12    // setter/getterは省略
13
14}

3.1.2. @CsvNumberFormat

数値型に対する書式を指定する際に利用するアノテーションです。

対応するJavaのクラスタイプは以下の通りです。

  • byte/short/int/long/float/double のプリミティブ型とそのラッパークラス。

  • java.math.BigDecimal / java.math.BigInteger の数値クラス。

注釈

プリミティブ型に対して読み込む際に、CSVのカラムの値が空の場合、それぞれのプリミティブ型の初期値が設定されます。

整数型の場合は 0 が、小数型の場合は 0.0 が設定されます。 初期値を変更したい場合は、アノテーション @CsvDefaultValue [JavaDoc]を使用してください。

3.1.2.1. 読み込み/書き込み時の書式を指定したい場合

  • 属性 pattern で書式を指定します。

  • 属性 locale でロケールを指定します。

    • 言語コードのみを指定する場合、'ja'の2桁で指定します。

    • 言語コードと国コードを指定する場合、'ja _JP'のようにアンダーバーで区切り指定します。

  • 属性 currency で通貨コード( ISO-4217コード )を指定します。

    • Javaのクラス java.util.Currency で解釈可能なコードを指定します。

  • 書式に合わない値をパースした場合、例外 SuperCsvValidationException が発生します。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvNumberFormat;
 4
 5@CsvBean
 6public class SampleCsv {
 7
 8    @CsvColumn(number=1)
 9    @CsvNumberFormat(pattern="#,##0")
10    private int number;
11
12    @CsvColumn(number=2, label="給与")
13    @CsvNumberFormat(pattern="\u00A4\u00A4 #,##0.0000", locale="ja_JP", currency="USD")
14    private Double salary;
15
16    // setter/getterは省略
17}

3.1.2.2. 読み込み時に曖昧に解析したい場合

曖昧なケースでも読み込めるようにしたいときは、属性 lenient の値をtrueにします。

例えば、 12.51 と小数を整数型にマッピングする場合、13 と丸めの補正が行われます。 また、 123,456.0ab のように、途中から数値以外の文字が出現した場合、それまでの文字 123,456.0 を抽出して処理が行われます。

注釈

数値型へのパースは、本ライブラリでは java.text.DecimalFormat を利用し、 結果を一旦 java.math.BigDecimal で読み込み、そこからさらに、各クラスタイプに変換しています。

DecimalFormat#parse(...) は、123,456.0abc のように、途中から数値以外の文字が出現した場合、それまでの文字を読み込み、正常処理することができます。

BigDecimal で、1234.567 という小数を読み込み、その値を BigDecimal#intValue() で整数のint型として取得した場合、小数部分は無視されます。 int型で扱える桁数を超えたときも自動的に切り捨てられます。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvNumberFormat;
 4
 5@CsvBean
 6public class SampleCsv {
 7
 8    @CsvColumn(number=1)
 9    @CsvNumberFormat(pattern="#,##0", lenient=true)
10    private int number;
11
12    @CsvColumn(number=2, label="給与")
13    @CsvNumberFormat(lenient=true)
14    private Double salary;
15
16    // setter/getterは省略
17}

3.1.2.3. 丸めの精度と方法を指定したい場合

  • 属性 precision で丸めの精度を指定することができます。

    • この属性は、属性patternを書式を指定しない場合に有効になります。

    • 主に小数の場合に有効桁数を揃える際に利用します。 例えば、precision=4で、文字列 123.45 を double型にマッピングする場合、結果は 123.4 として読み込まれます。

  • 属性 rounding で、丸め方の方法を指定します。

    • 値は、列挙型 java.math.RoundingMode を設定します。

    • デフォルトでは、RoundingMode.HALF_EVEN です。 詳細は、 RoundingModeのJavaDoc を参照してください。

    • 属性patternを指定した場合は、書式自身が精度を表現しており、属性roundingで丸めの方法を指定することができます。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvNumberFormat;
 4
 5import java.math.RoundingMode;
 6
 7@CsvBean
 8public class SampleCsv {
 9
10    // 丸めの精度と方法を指定する場合
11    @CsvColumn(number=1, label="比率")
12    @CsvNumberFormat(precision=4, rounding=RoundingMode.HALF_UP)
13    private double rate;
14
15    // 書式と丸め方法を指定する場合
16    @CsvColumn(number=2, label="給与")
17    @XlsNumberFormat(pattern="#,##0", rounding=RoundingMode.CEILING, lenient=true)
18    private int salary;
19
20    // setter/getterは省略
21}

3.1.2.4. 読み込み時の値のパースに失敗した際のメッセージ

読み込み時に値のパースに失敗した時に独自のメッセージとして、属性 message で指定することができます。

メッセージ中は、JEXL による式言語を使うことができ、 予め登録されている変数を用いて、メッセージ内容を独自にカスタマイズすることができます。 詳細は、値の検証時のメッセージ を参照してください。

メッセージ中で利用可能な変数は、JavaDoc を参照してください。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvNumberFormat;
 4
 5@CsvBean
 6public class SampleCsv {
 7
 8    @CsvColumn(number=1, label="給料")
 9    @CsvNumberFormat(pattern="", message="[{rowNumber}行, {columnNumber}列] : 項目「{label}」の値({validatedValue})は、整数の書式「{pattern}」として不正です。"
10    private int salary;
11
12    // setter/getterは省略
13}

3.1.3. @CsvDateTimeFormat

日時型に対する書式を指定する際に利用するアノテーションです。

アノテーションを付与しないときや属性 pattern を指定しないときは、クラスタイプごとに決まった標準の書式が適用されます。 対応するJavaのクラスタイプと標準の書式は以下の通りです。

表 - 3.1.2 対応する日時のクラスタイプと標準の書式

クラスタイプ

標準の書式

java.util.Date

yyyy-MM-dd HH:mm:ss

java.util.Calendar

yyyy-MM-dd HH:mm:ss

java.sql.Date

yyyy-MM-dd

java.sql.Time

HH:mm:ss

java.sql.Timestamp

yyyy-MM-dd HH:mm:ss.SSS

java.time.LocalDateTime

uuuu-MM-dd HH:mm:ss

java.time.LocalDate

uuuu-MM-dd

java.time.ZonedDateTime

uuuu-MM-dd HH:mm:ssxxx'['VV']'

org.joda.time.LocalDateTime

yyyy-MM-dd HH:mm:ss

org.joda.time.LocalDate

yyyy-MM-dd

org.joda.time.LocalTime

HH:mm:ss

org.joda.time.DateTime

yyyy-MM-dd HH:mm:ssZZ

3.1.3.1. 読み込み/書き込み時の書式を指定したい場合

  • 属性 pattern で書式を指定します。

    • 省略した場合、クラスタイプごとの標準の書式が適用されます。

    • java.util.Date/java.util.Calendar/java.sql.XXXX系のクラスの場合、 java.text.SimpleDateFormat で解釈可能な書式を設定します。

    • java.time.XXX系のクラスの場合、 java.time.format.DateTimeFormatter で解釈可能な書式を設定します。

    • org.joda.time.XXX系のクラスの場合は、 org.joda.time.format.DateTimeFormat で解釈可能な書式を設定します。

  • 属性 locale でロケールを指定します。

    • 言語コードのみを指定する場合、 ja の2桁で指定します。

    • 言語コードと国コードを指定する場合、 ja_JP のようにアンダーバーで区切り指定します。

    • 和暦を扱う時など、バリアントを指定する場合も同様に、 ja_JP_JP のようにさらにアンダーバーで区切り指定します。

  • 属性 timezone でタイムゾーンを指定します。

    • Asia/Tokyo, GMT, GMT+09:00などの値を指定します。

    • ただし、オフセットを持たないクラスタイプ「LocalDateTime, LocalDate, LocalTime」の時は、指定しても意味がありません。

  • 書式に合わない値をパースした場合、例外 SuperCsvValidationException が発生します。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvDateTimeFormat;
 4
 5import java.util.Date;
 6import java.time.LocalDateTime;
 7
 8@CsvBean
 9public class SampleCsv {
10
11    // 和暦を扱う場合
12    @CsvColumn(number=1)
13    @CsvDateTimeFormat(pattern="GGGGyy年MM月dd日", locale="ja_JP_JP")
14    private Date japaneseDate;
15
16    @CsvColumn(number=2, label="更新日時")
17    @CsvDateTimeFormat(pattern="uuuu/MM/dd HH:mm:ss")
18    private LocalDateTime updateTime;
19
20    // setter/getterは省略
21}

3.1.3.2. 読み込み時に曖昧に解析したい場合

曖昧なケースでも読み込めるようにしたいときは、属性 lenient の値をtrueにします。

例えば、 2016-02-31 と存在しない日を解析する場合、 2016-03-02 と補正が行われます。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvDateTimeFormat;
 4
 5import java.time.LocalDate;
 6
 7@CsvBean
 8public class SampleCsv {
 9
10    @CsvColumn(number=1, label="誕生日")
11    @CsvDateTimeFormat(lenient=true)
12    private LocalDate birthday;
13
14    // setter/getterは省略
15}

3.1.3.3. 読み込み時の値のパースに失敗した際のメッセージ

読み込み時に値のパースに失敗した時に独自のメッセージとして、属性 message で指定することができます。

メッセージ中は、JEXL による式言語を使うことができ、 予め登録されている変数を用いて、メッセージ内容を独自にカスタマイズすることができます。 詳細は、値の検証時のメッセージ を参照してください。

メッセージ中で利用可能な変数は、JavaDoc を参照してください。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvDateTimeFormat;
 4
 5import java.time.LocalDate;
 6
 7@CsvBean
 8public class SampleCsv {
 9
10    @CsvColumn(number=1, label="誕生日")
11    @CsvDateTimeFormat(pattern="uuuu/M/d", message="[{rowNumber}行, {columnNumber}列] : 項目「{label}」の値({validatedValue})は、日付の書式「{pattern}」として不正です。"
12    private LocalDate birthday;
13
14    // setter/getterは省略
15}

3.1.4. @CsvEnumFormat

列挙型の変換規則の設定を行うためのアノテーションです。

3.1.4.1. 基本的な使い方

列挙型の場合、アノテーション @CsvEnumFormat を付与しなくてもマッピングできます。 その際は、カラムの値と列挙型の要素の値をマッピングさせます。 要素の値とは、 Enum#name() で取得できる値です。

  • 属性 ignoreCase の値をtrueにすると、読み込み時に大文字/小文字の区別なく変換します。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvEnumFormat;
 4
 5@CsvBean
 6public class SampleCsv {
 7
 8    @CsvColumn(number=1, label="権限")
 9    private RoleType role;
10
11    // 読み込み時に大文字・小文字の区別を行いません。
12    @CsvColumn(number=2, label="権限2")
13    @CsvEnumFormat(ignoreCase=true)
14    private RoleType role2;
15
16    // setter/getterは省略
17}
18
19// 列挙型の定義
20public enum RoleType {
21    Normal, Admin;
22}

3.1.4.2. 別名でマッピングする場合

別名でマッピングする場合、属性 selector で列挙型の要素の別名を取得するメソッド名を指定します。

次の例では、読み込み時に入力値が 一般権限 の場合、 RoleType.Normal にマッピングされます。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvEnumFormat;
 4
 5@CsvBean
 6public class SampleCsv {
 7
 8    @CsvColumn(number=1, label="権限")
 9    @CsvEnumFormat(selector="localeName")
10    private RoleType role;
11
12    // setter/getterは省略
13}
14
15// 列挙型の定義
16public enum RoleType {
17    Normal("一般権限"), Admin("管理者権限");
18
19    // 別名の設定
20    private String localeName;
21
22    private RoleType(String localeName) {
23        this.localeName = localeName;
24    }
25
26    // 別名の取得用メソッド
27    public String localeName() {
28        return this.localeName;
29    }
30
31}

3.1.4.3. 読み込み時の値のパースに失敗した際のメッセージ

読み込み時に値のパースに失敗した時に独自のメッセージとして、属性 message で指定することができます。

メッセージ中は、JEXL による式言語を使うことができ、 予め登録されている変数を用いて、メッセージ内容を独自にカスタマイズすることができます。 詳細は、値の検証時のメッセージ を参照してください。

メッセージ中で利用可能な変数は、JavaDoc を参照してください。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.format.CsvEnumFormat;
 4
 5@CsvBean
 6public class SampleCsv {
 7
 8    @CsvColumn(number=1, label="ステータス")
 9    @CsvEnumFormat(message="[{rowNumber}行, {columnNumber}列] : 項目「{label}」の値({validatedValue})は、何れかの値「${f:join(enums, ', ')}」である必要があります。"
10    private RoleType role;
11
12    // setter/getterは省略
13}
14
15// 列挙型の定義
16public enum RoleType {
17    Normal, Admin;
18}

3.2. 独自のクラスタイプへの対応

独自の変換処理を実装するには、2つのステップを踏む必要があります。

  1. TextFormatter の実装クラスの作成

  2. アノテーション @CsvFormat で作成したTextFormatterの指定

以下、それぞれに対して解説していきます。

3.2.1. TextFormatterの実装クラスの作成

サンプルとして、 java.net.URL にマッピングするTextFromatterを作成します。

  • 抽象クラス AbstractTextFormatter [ JavaDoc ] を継承します。

  • メソッド parse(...) で、読み込み時の文字列からオブジェクト型に変換するメソッドの実装を行います。

    • 変換に失敗した場合、例外 TextParseException をスローします。 既存の例外が発生する場合は、ラップするようにします。

  • メソッド print(...) で、書き込みにオブジェクト型から文字列に変換するメソッドの実装を行います。

    • 変換に失敗した場合、例外 TextPrintException をスローします。 既存の例外が発生する場合は、ラップするようにします。

  • メソッド getMessageVariables(...) で、エラーメッセージ中の変数を定義することができます。

    • 必要がなければ実装する必要はありません。

 1import java.net.MalformedURLException;
 2import java.net.URL;
 3import java.util.HashMap;
 4import java.util.Map;
 5
 6import com.github.mygreen.supercsv.cellprocessor.format.AbstractTextFormatter;
 7import com.github.mygreen.supercsv.cellprocessor.format.TextParseException;
 8
 9// URLにマッピングするクラス
10public class UrlFormatter extends AbstractTextFormatter<URL> {
11
12    // 読み込み時の文字列からオブジェクト型に変換するメソッドの実装
13    @Override
14    public URL parse(final String text) {
15
16        try {
17            return new URL(text);
18        } catch(MalformedURLException e) {
19            throw new TextParseException(text, URL.class, e);
20        }
21
22    }
23
24    // 書き込みにオブジェクト型から文字列に変換するメソッドの実装
25    @Override
26    public String print(final URL object) {
27        return object.toExternalForm();
28    }
29
30    // 読み込み時のエラーメッセージ中で使用可能な変数の定義
31    // 必要があればオーバライドして実装します。
32    @Override
33    public Map<String, Object> getMessageVariables() {
34
35        final Map<String, Object> vars = new HashMap<>();
36
37        vars.put("key", "vars");
38
39        return vars;
40    }
41
42}

3.2.2. 作成したTextFormatterの指定

作成したTextFormatterを指定するには、アノテーション @CsvFormat [ JavaDoc ]を使用します。

  • 属性 formatter で、TextFormatterの実装クラスを指定します。

  • 属性 message で、読み込み時のエラーメッセージを指定することができます。

 1import java.net.URL;
 2
 3import com.github.mygreen.supercsv.annotation.CsvBean;
 4import com.github.mygreen.supercsv.annotation.CsvColumn;
 5import com.github.mygreen.supercsv.annotation.format.CsvFormat;
 6
 7@CsvBean
 8public class SampleCsv {
 9
10    @CsvColumn(number=1, label="ホームページ")
11    @CsvFormat(formatter=UrlFormatter.class,
12            message="[{rowNumber}行, {columnNumber}列] : 項目「{label}」の値({validatedValue})は、URLの形式として不正です。"
13    private URL homepage;
14
15    // setter/getterは省略
16
17}