【发布时间】:2020-03-12 14:41:14
【问题描述】:
我想将带有标题但列号未知的通用 CSV 文件读入类型化结构。我的问题有点像Strongly typed access to csv in scala?,但事实上我没有架构可以传递给解析器......
到目前为止,我一直在使用 Jackson CSV 映射器将每一行作为 Map[String,String] 读取,并且运行良好。
import com.fasterxml.jackson.module.scala.DefaultScalaModule
def genericStringIterator(input: InputStream): Iterator[Map[String, String]] = {
val mapper = new CsvMapper()
mapper.registerModule(DefaultScalaModule)
val schema = CsvSchema.emptySchema.withHeader
val iterator = mapper
.readerFor(classOf[Map[String, String]])
.`with`(schema)
.readValues[Map[String, String]](input)
iterator.asScala
}
现在,我们需要输入字段,因此 4.2 将是一个 Double 但“4.2”仍然是一个字符串。
我们在项目中到处都在使用 play-json,所以我知道 JsValue 已经对类似的通用东西有很好的类型推断。
作为 paly-json,它也是基于 Jackson 的,我认为拥有类似的东西会很棒
import play.api.libs.json.jackson.PlayJsonModule
def genericStringIterator(input: InputStream): Iterator[JsValue] = {
val mapper = new CsvMapper()
mapper.registerModule(PlayJsonModule)
val schema = CsvSchema.emptySchema.withHeader
val iterator = mapper
.readerFor(classOf[JsValue])
.`with`(schema)
.readValues[JsValue](input)
iterator.asScala
}
但是当我尝试以前的代码时,我得到了一个异常:
val iterator = CSV.genericAnyIterator(input(
"""foo,bar,baz
|"toto",42,43
|"tata",,45
| titi,87,88
|"tutu",,
|""".stripMargin))
iterator
.foreach { a =>
println(a)
}
java.lang.RuntimeException: We should be reading map, something got wrong
at play.api.libs.json.jackson.JsValueDeserializer.deserialize(JacksonJson.scala:165)
at play.api.libs.json.jackson.JsValueDeserializer.deserialize(JacksonJson.scala:128)
at play.api.libs.json.jackson.JsValueDeserializer.deserialize(JacksonJson.scala:123)
at com.fasterxml.jackson.databind.MappingIterator.nextValue(MappingIterator.java:277)
at com.fasterxml.jackson.databind.MappingIterator.next(MappingIterator.java:192)
at scala.collection.convert.Wrappers$JIteratorWrapper.next(Wrappers.scala:40)
at scala.collection.Iterator.foreach(Iterator.scala:929)
at scala.collection.Iterator.foreach$(Iterator.scala:929)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1417)
at my.company.csv.CSVSpec$$anon$4.<init>(CSVSpec.scala:240)
是不是我做错了什么?
我不关心最后是否有一个 play-json JsValue,任何具有通用类型字段的 Json 结构都可以。我可以使用另一个库吗?对于我的发现,所有其他库都是基于预先提供给 CSV Reader 的映射,对我来说重要的是能够从 CSV 推断类型。
【问题讨论】:
-
在这种情况下有点矫枉过正,但你可以用 Shapeless 解决这个问题。
-
@sinanspd 我不确定 Shapeless 是否可以提供帮助。 PureCSV 基于 shapeless 但仍需要声明将要读取的类型。
标签: json scala csv jackson play-json