通过扩展 java class 在 Scala 中解析 Json
Parsing Json in scala with extending java class
我有一个 java class 如下
public class JobConfig implements Serializable {
private String appName;
//some other params
public JobConfig() {
}
// getters setters
我正在尝试在 scala
中扩展上述 java class
class CsvJobConfig extends JobConfig(){
var delimiter =null
//other attributes
现在在主要 class 中,我正在尝试解析 json 并将其分配回 CsvJobConfig 。
val is = fileReader.getInputStreamFor(configFileName, configPath, spark)
var jobConfigJson = IOUtils.toString(is, Charset.defaultCharset.name)
val mapper = new ObjectMapper
val config = mapper.readValue(jobConfigJson, classOf[CsvJobConfig]).asInstanceOf[CsvJobConfig]
下面是示例json 我正在尝试解析
{
"appName":"abc",
"delimiter": "\|\|"
}
虽然从 java 尝试时它工作正常,但它在 scala
中给我以下错误
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "delimiter" (class CsvJobConfig), not marked as ignorable (1 known properties: ["appName"])
"[truncated 405 chars]; line: 29, column: 17] (through reference chain: CsvJobConfig["delimiter"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:52)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:839)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1045)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1352)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1330)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:264)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2726)
at com.mastercard.dw.etl.spark.FlatFileProcessor$.delayedEndpoint$com$mastercard$dw$etl$spark$FlatFileProcessor(FlatFileProcessor.scala:30)
at com.mastercard.dw.etl.spark.FlatFileProcessor$delayedInit$body.apply(FlatFileProcessor.scala:11)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main.apply(App.scala:76)
at scala.App$$anonfun$main.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:392)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
值得一试
var delimiter: String = null
在你的代码中,变量delimiter的类型是Null类型,可能会导致这个异常。
ObjectMapper 必须配置为不 FAIL_ON_UNKNOWN_PROPERTIES 参考下面的代码,并且还分配 scala 中变量的类型 class。
class CsvJobConfig extends JobConfig {
var delimiter: String = null
}
import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
val config: CsvJobConfig = mapper.readValue("{\"appName\":\"abc\", \"delimiter\": \"\\|\\|\"}", classOf[CsvJobConfig])
println(config)
println(config.delimiter)
添加mapper.registerModule(DefaultScalaModule)
并有一个案例 class 解决了这个问题。
在 scala class 中手动添加 setter 方法也可以解决问题。
我有一个 java class 如下
public class JobConfig implements Serializable {
private String appName;
//some other params
public JobConfig() {
}
// getters setters
我正在尝试在 scala
中扩展上述 java classclass CsvJobConfig extends JobConfig(){
var delimiter =null
//other attributes
现在在主要 class 中,我正在尝试解析 json 并将其分配回 CsvJobConfig 。
val is = fileReader.getInputStreamFor(configFileName, configPath, spark)
var jobConfigJson = IOUtils.toString(is, Charset.defaultCharset.name)
val mapper = new ObjectMapper
val config = mapper.readValue(jobConfigJson, classOf[CsvJobConfig]).asInstanceOf[CsvJobConfig]
下面是示例json 我正在尝试解析
{
"appName":"abc",
"delimiter": "\|\|"
}
虽然从 java 尝试时它工作正常,但它在 scala
中给我以下错误 Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "delimiter" (class CsvJobConfig), not marked as ignorable (1 known properties: ["appName"])
"[truncated 405 chars]; line: 29, column: 17] (through reference chain: CsvJobConfig["delimiter"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:52)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:839)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1045)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1352)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1330)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:264)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2726)
at com.mastercard.dw.etl.spark.FlatFileProcessor$.delayedEndpoint$com$mastercard$dw$etl$spark$FlatFileProcessor(FlatFileProcessor.scala:30)
at com.mastercard.dw.etl.spark.FlatFileProcessor$delayedInit$body.apply(FlatFileProcessor.scala:11)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main.apply(App.scala:76)
at scala.App$$anonfun$main.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:392)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
值得一试
var delimiter: String = null
在你的代码中,变量delimiter的类型是Null类型,可能会导致这个异常。
ObjectMapper 必须配置为不 FAIL_ON_UNKNOWN_PROPERTIES 参考下面的代码,并且还分配 scala 中变量的类型 class。
class CsvJobConfig extends JobConfig {
var delimiter: String = null
}
import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
val config: CsvJobConfig = mapper.readValue("{\"appName\":\"abc\", \"delimiter\": \"\\|\\|\"}", classOf[CsvJobConfig])
println(config)
println(config.delimiter)
添加mapper.registerModule(DefaultScalaModule) 并有一个案例 class 解决了这个问题。 在 scala class 中手动添加 setter 方法也可以解决问题。