Apache Spark 2.0: java.lang.UnsupportedOperationException: нет кодера для java.time.LocalDate

Я использую Apache Spark 2.0 и создаю case class для обозначения схемы для DetaSet. Когда я пытаюсь определить пользовательский кодер в соответствии с Как сохранить пользовательские объекты в Dataset?, для 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-кодер для искры?

Обновление

Когда я создаю кодировщик для всего класса case, 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, но возвращаю бинарную карту.

Ответ 1

Как говорится в последнем комментарии, "если класс содержит поле Bar, вам нужен кодер для целого объекта". Вам нужно предоставить неявный Encoder для самого FireService; иначе Spark построит один для вас с помощью SQLImplicits.newProductEncoder[T <: Product : TypeTag]: Encoder[T]. Вы можете видеть по типу, что он не использует никаких параметров implicit Encoder для полей, поэтому он не может использовать присутствие localDateEncoder.

Искра может быть изменена для обработки этого, например. используя библиотеку Shapeless или напрямую используя макросы; Я не знаю, будет ли это план в будущем.