使用扩展的Java类在Scala中解析Json

问题描述

我有一个如下的java类

public class JobConfig implements Serializable {
private String appName;
//some other params
public JobConfig() {
}
// getters setters 

我正在尝试在scala中扩展上述java类

class CsvJobConfig extends JobConfig(){
var delimiter =null
//other attributes

现在,在主类中,我正在尝试解析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$1(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$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.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)

解决方法

ObjectMapper必须配置为不通过FAIL_ON_UNKNOWN_PROPERTIES引用以下代码,并在scala类中分配变量的类型。

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)
,

值得尝试的

var delimiter: String = null

在您的代码中,变量定界符的类型为Null类型,这可能导致此异常。

,

添加mapper.registerModule(DefaultScalaModule) 并设有案例类解决了这个问题。 另外,在scala类中手动添加setter方法也可以解决该问题。