Reputation: 79
I have written a Scala program using Jackson framework to read a Json file. I'm getting the following error whenever executing Scala program. Could anyone suggest how I can overcome this error.
Error
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class Definition]: can not instantiate from JSON object (need to add/enable type information?)
at [Source: { "recordDefinitions": [ { "recordDefinitionIdentifier": 2, "recordTypeCode": "LT", "recordTypePattern": "^.{14}LT.*$", "minimumNumberOfAttributes": 19, "expectedNumberOfAttributes": 19, "recordLength": 117, "attributes": [ { "attributeIdentifier": 1, "attributeName": "PROVIDER TYPE", "attributeMaximumLength": 1, "datatype": { "datatypeName": "AN" } } ] } ]}; line: 1, column: 4]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1071)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:264)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:124)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3066)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2161)
at Json_Parser_Jackson$.main(Json_Parser_Jackson.scala:33)
at Json_Parser_Jackson.main(Json_Parser_Jackson.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Program
import java.io.{File, StringWriter}
import java.util
import com.fasterxml.jackson.core.`type`.TypeReference
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import org.apache.avro.ipc.specific.Person
import scala.io.Source
case class Definition(recordDefinitions: Seq[RecordDefinitionsClass])
case class RecordDefinitionsClass(recordDefinitionIdentifier:Int,recordTypeCode: String,recordTypePattern:String,minimumNumberOfAttributes: Int,expectedNumberOfAttributes: Int,recordLength:Int,attributes: Seq[Attributes])
case class Attributes(attributeIdentifier: Int,attributeName:String,attributeMaximumLength:Int,datatype: Seq[DataType])
case class DataType(datatypeName:String)
object Json_Parser_Jackson {
def main(args: Array[String]): Unit = {
val fileContent = Source.fromFile("C:\\Users\\xxxnd\\ideaProject\\jsonparser\\src\\main\\resources\\Json_file.json","UTF-8").getLines.mkString
val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)
val person2: Definition = new ObjectMapper().readValue(fileContent,classOf[Definition])
println(person2)
}
}
Json File
{
"recordDefinitions": [
{
"recordDefinitionIdentifier": 2,
"recordTypeCode": "LT",
"recordTypePattern": "^.{14}LT.*$",
"minimumNumberOfAttributes": 19,
"expectedNumberOfAttributes": 19,
"recordLength": 117,
"attributes": [
{
"attributeIdentifier": 1,
"attributeName": "PROVIDER TYPE",
"attributeMaximumLength": 1,
"datatype": {
"datatypeName": "AN"
}
}
]
}
]
}
Upvotes: 1
Views: 3790
Reputation: 948
To spell out a concrete solution and save some of you time, this is the best way I have found:
case class MyData(@JsonProperty("myStringVar") myStringVar: String,
@JsonProperty("my_renamed_var") myRenamedVar: Int)
NB. Below Jackson 3.x[0], you will need to repeat the variable name in the annotation even if you don't rename it. In that case, you can consider including the jackson-modules-java8 you should be able to simply add a @JsonProperty
annotation.
You can also add an empty constructor and @BeanProperty
annotations, if you prefer a pure Scala approach.
[0] Such as version 2.6.7.1 of jackson-databind currently required by the AWS Lambda Java SDK.
Upvotes: 0
Reputation: 437
If I am not mistaking, Scala case class does not have a parameterless constructor, but a constructor with all fields as parameters and an apply
method of the companion object. Jackson object mapper, however requires a parameterless constructor to instantiate the class first. So the most "jackson" way would be to create a Java POJO instead of a case class like here: Jackson Github
I would suggest you to use something like this: Implicit JSON conversion
Also see this answer.
Upvotes: 1