2016-08-03 55 views
10

我正在使用Apache Spark 2.0並創建case class作爲DetaSet的提及架構。當我試圖定義根據How to store custom objects in Dataset?定製的編碼器,爲java.time.LocalDate我有以下異常:Apache Spark 2.0:java.lang.UnsupportedOperationException:沒有爲java.time.LocalDate找到編碼器

java.lang.UnsupportedOperationException: No Encoder found for java.time.LocalDate 
- field (class: "java.time.LocalDate", name: "callDate") 
- root class: "FireService" 
at org.apache.spark.sql.catalyst.ScalaReflection$.org$apache$spark$sql$catalyst$ScalaReflection$$serializerFor(ScalaReflection.scala:598) 
at org.apache.spark.sql.catalyst.ScalaReflection$$anonfun$9.apply(ScalaReflection.scala:592) 
at org.apache.spark.sql.catalyst.ScalaReflection$$anonfun$9.apply(ScalaReflection.scala:583) 
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241) 
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241) 
at scala.collection.immutable.List.foreach(List.scala:381) 
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:241) 
............ 

以下爲代碼:

case class FireService(callNumber: String, callDate: java.time.LocalDate) 
implicit val localDateEncoder: org.apache.spark.sql.Encoder[java.time.LocalDate] = org.apache.spark.sql.Encoders.kryo[java.time.LocalDate] 

val fireServiceDf = df.map(row => { 
val dateFormatter = java.time.format.DateTimeFormatter.ofPattern("MM/dd /yyyy") 
FireService(row.getAs[String](0), java.time.LocalDate.parse(row.getAs[String](4), dateFormatter)) 
}) 

如何,我們可以定義第三方API的編碼器的火花?

更新

當我創建了整個案件類的編碼器,df.map..映射爲下面的對象轉換爲二進制,:

implicit val fireServiceEncoder: org.apache.spark.sql.Encoder[FireService] = org.apache.spark.sql.Encoders.kryo[FireService] 

val fireServiceDf = df.map(row => { 
val dateFormatter = java.time.format.DateTimeFormatter.ofPattern("MM/dd/yyyy") 
FireService(row.getAs[String](0), java.time.LocalDate.parse(row.getAs[String](4), dateFormatter)) 
}) 

fireServiceDf: org.apache.spark.sql.Dataset[FireService] = [value: binary] 

我期待地圖FireService,但返回地圖的二進制。

回答

4

正如最後一條評論那樣,「如果class包含一個字段Bar,則需要爲整個對象編碼器。」您需要爲FireService本身提供隱式編碼器;否則Spark將使用SQLImplicits.newProductEncoder[T <: Product : TypeTag]: Encoder[T]爲您構建一個。您可以從類型看出它沒有使用任何implicit字段的編碼器參數,因此它不能使用localDateEncoder的存在。

可以改變Spark來處理這個例如使用Shapeless庫或直接使用宏;我不知道這是否是未來的計劃。

+0

嗨@Alexey我還沒有明確的理由,爲什麼我們需要全對象格式化程序? –

+0

我明白了你的觀點。我也更新了這個問題,因爲現在我的數據被轉換爲二進制。當我使用Timestamp而不是LocalDate時,dataschema構建爲FireService,否則構建爲Binary。 –

+0

請作爲一個單獨的問題。一般來說,不要編輯問題來詢問不同的問題。 –

相關問題