the hacker
the hacker

Reputation: 79

No suitable constructor found for type [simple type, class Definition]

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

Answers (2)

LCC
LCC

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

Sergey
Sergey

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

Related Questions