28
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CSV Schemaを使ったCSVのお手軽入力チェック

Last updated at Posted at 2015-06-18

CSV Schemaとは

  • 簡単に言うとCSVデータの定義とValidationを目的としたDSLです
    • ほぼJSON SchemaのCSV版といってよさそうです
  • 仕様はこちらをどうぞ

CSVこれまで

  • CSVはRFC4180 - 日本訳で標準化されてますが、策定が遅かったため各ベンダー間でデータ形式がバラバラです
  • それによって特に困る領域の一つにEDI(データ交換)があります
    なにせ各システムが示すCSVが実際どのようなフォーマットなのか、認識を合わせするところから始まる必要があります
    • (例)区切り文字が「カンマ」or「タブ」 か
    • (例)囲み文字が「ダブルクォート」or「シングルクウォート」or「無し」 か
    • (例)エスケープの有無
    • (例)ヘッダ行の有無
    • (例)項目中の改行や区切り文字はどういう仕様で扱うか
    • etc.
  • これがクリア出来た後に、実際のデータ項目のがどのような意味か(IDとか金額とか)の話をすることが出来ます

項目チェック

  • ある項目がユーザIDを指し、ユーザIDは8桁で半角英数字のみで構成されますという約束でデータ連携した時、これの入力チェックは非常に簡単なように思われます。なにせ約束したのですから。

  • ただし実際は 世 の 中 甘 く 出 来 て い な い です

  • まず桁数が6桁で連携してきます。担当者に連絡すると、あろうことかそれが正しい仕様だと言ってくるんです。
    8桁と言っていたのに、です。6桁をどうしろって? こちらのシステムで左から0埋めしてくれと言うんです。
    初耳ですよその仕様!?最初から言ってよ!

  • 半角英数字? 当然のように記号が入ってきます。ハイフンやアンダースコアです。これは英数字なんですかね?
    半角英数字って[0-9a-zA-Z]って定義しましたよね?

  • また記号が入ってました。おお、今度は半角スペースですか。なるほど、非エンジニアであればあまり意識しないかもしれないね!正規表現まで提示したのにガン無視ですね!

* 今回は非常にシンプルなケースでしたが、連携データが「売掛金」など金銭を扱うケースだとより神経質にチェックを行わざる負えず、非常に苦労が耐えません。
あー、もっと簡単にデータチェックしたいのにー
 

というわけでCSV Schemaです

  • CSV SchemaはCSVデータの構造定義を表現する標準的な仕様です

  • 今までのCSV定義は各々が勝手に決めて作ったり、必ずしもプログラムからの読み取りに適したフォーマットではなかったので、定義が標準化されるのは非常に嬉しいことなのです

    • これでJSON-Schemaを羨ましがらなくてすみます!
  • 更にCSV-Schemaという標準化された定義から、各言語技術ごとにValidationツールが出てくると思いますので、これをお互い利用することでちょっとした認識の違いを早期に発見できます。良かったよかった。

実装

すでにCSV SchemaによるValidationを実装されていたモジュールがあったので試してみます。

CSV Validator
A Validation Tool and APIs for validating CSV (Comma Separated Value) files by using CSV Schema.
https://github.com/digital-preservation/csv-validator

条件

入力のCSVです。
色々データが不正です。

入力データ(ivalid.csv)
name,age,gender
james,4 years,m
lauren,19,f
simon,57,malename,age,gender
james,21,m
lauren,19,f
simon,57,m

CSVスキーマです。
CSVスキーマなのにCSVで表現しないんだってツッコミは無しですよ。
拡張子は.csvsみたいです。

CSVスキーマ(example.csvs)
version 1.0
@totalColumns 3
name: notEmpty
age: range(0, 120)
gender: is("m") or is("f") or is("t") or is("n") 

依存ライブラリです

pom.xml
<dependency>
    <groupId>uk.gov.nationalarchives</groupId>
    <artifactId>csv-validator-java-api</artifactId>
    <version>1.0</version>
</dependency>

実行コードです。
importはuk.gov.nationalarchives.csv.validator.api.javaのパッケージの方で
コンパイルが通りました。

本家のコードを少し修正
		List<Substitution> pathSubstitutions = new ArrayList<>();

		// CSV検証の実行
		List<FailMessage> messages = CsvValidator.validate("invalid.csv",// CSVファイル
				"example.csvs", // CSVスキーマファイル
				false, // 最初にエラーが発生したら処理を中断するか
				pathSubstitutions, // ファイルパスの格納用
				true // ファイルパスの厳格なチェック
				);

		if (messages.isEmpty()) {
			System.out.println("Completed validation OK");
			return;
		}
		
		for (FailMessage message : messages) {
			if (message instanceof WarningMessage) {
				System.out.println("[WARN] " + message.getMessage());
			} else {
				System.out.println("[ERROR] " + message.getMessage());
			}
		}

実行結果

想定通り、3項目が定義違反で怒られています。

  • 1行目のageの値が0~120の間にない
  • 3行目のカラム数が5個ある
  • 3行目のgenderがm,f,t,nの値ではない

まだまだ改善の余地はありそうですが、内容としては十分ではないでしょうか。

実行結果
[ERROR] range(0,120) fails for line: 1, column: age, value: "4 years"
[ERROR] Expected @totalColumns of 3 and found 5 on line 3
[ERROR] is("m") or is("f") or is("t") or is("n") fails for line: 3, column: gender, value: "malename"

おしまい

  • CSV Schema、もっと流行ると良いですね!
  • CSVもっと使いましょう!XMLでのデータ交換は滅びろ。
28
25
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?