LoginSignup
4
3

More than 5 years have passed since last update.

Java で CSV をヘッダの名前ベースでデシリアライズする

Last updated at Posted at 2018-09-19

コードは Kotlin だけどよしなに読み替えてください。

前提

  • Excel は便利なのでこれを使ってまとめて書きたい。どかっと記述して CSV で取り込みたい。
  • とにかくフィールドが多い、可変かもしれない、増えるかもしれないし減るかもしれない。

やっていく

jackson-dataformat-csv を使えばできる。
https://github.com/FasterXML/jackson-dataformats-text/tree/master/csv

ドキュメントがかなりふわっとしていて難解だがやればできる。

import assertk.assert
import assertk.assertions.isEqualTo
import assertk.assertions.isNotNull
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonUnwrapped
import com.fasterxml.jackson.dataformat.csv.CsvMapper
import com.fasterxml.jackson.dataformat.csv.CsvSchema
import org.junit.Test

class DeserializeTest {
    enum class Country {
        JP,
        US
    }

    class Profile {
        @JsonProperty("age")
        val age: Int = 0

        @JsonProperty("country")
        val country: Country = Country.JP
    }

    class User {
        @JsonProperty("_id")
        val id: Int = 0

        @JsonProperty("name")
        val name: String = ""

        @JsonUnwrapped(prefix = "profile.")
        val profile: Profile? = null
    }

    @Test
    fun deserialize() {
        val mapper = CsvMapper()
        val schema = CsvSchema.emptySchema().withHeader()

        val reader = mapper.readerFor(User::class.java).with(schema)
        val users = reader.readValues<User>("""
name,_id,profile.age,profile.country
foo,3,17,JP
bar,2,21,US
        """.trim()).readAll()

        assert(users[0].id).isEqualTo(3)
        assert(users[0].name).isEqualTo("foo")
        assert(users[0].profile).isNotNull {
            assert(it.actual.age).isEqualTo(17)
            assert(it.actual.country).isEqualTo(Country.JP)
        }

        assert(users[1].id).isEqualTo(2)
        assert(users[1].name).isEqualTo("bar")
        assert(users[1].profile).isNotNull {
            assert(it.actual.age).isEqualTo(21)
            assert(it.actual.country).isEqualTo(Country.US)
        }
    }
}

ポイントは CsvSchema に型情報を与えないこと。
ここで型情報を渡すととにかくカラムの順序ベースでしかデシリアライズしてくれなくてはまる。
@JsonUnwrapped が地味にすごい。便利。
JavaBeans を要求されるので Kotlin で書いているなら non-null については諦めてください。悲しいですね。

4
3
0

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
4
3