1
votes

I want to deserialize json with jackson in scala

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator; 



case class Metadata(@JsonProperty("hive_type_string") hive_type_string: String)

case class Field(@JsonProperty("name") name: String, @JsonProperty("type") typeField: String, @JsonProperty("nullable") nullable: Boolean, @JsonProperty("metadata") metadata: Metadata) 

case class StructTable(@JsonProperty("type") typeField: String, @JsonProperty("fields") fields: Seq[Field])


val mapper = new ObjectMapper() with ScalaObjectMapper
mapper.registerModule(DefaultScalaModule)
val struct = mapper.readValue[StructTable](json_struct)

json_struct :

{ "type":"struct", "fields":[ { "name":"code_role", "type":"string", "nullable":true, "metadata":{ "HIVE_TYPE_STRING":"string" } }, { "name":"libelle_role", "type":"string", "nullable":true, "metadata":{ "HIVE_TYPE_STRING":"string" } } ] }

This is the error : com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of StructTable: non-static inner classes like this can only by instantiated using default, no-argument constructor

Can someone help me ?

Thanks.

1
You need to post the actual code that fails rather than just snippets, and try to pare it down to the simplest version that shows the problem.Tim
Do you really need to use a runtime-reflection based Java library. Instead dog any of the many Scala libraries which derive the decoders at compile time being safer and faster?Luis Miguel Mejía Suárez
@Tim It is the actual code, the error is related to the last line : val struct = mapper.readValue[StructTable](json_struct)Arthhur10
Do you have something simple to use @LuisMiguelMejíaSuárez ?Arthhur10
A couple of options: circe, uJson, jsonitter-scala, etc.Luis Miguel Mejía Suárez

1 Answers

1
votes

If you can pick another library like jsoniter-scala then add to your dependencies:

libraryDependencies ++= Seq(
  // Use the %%% operator instead of %% for Scala.js  
  "com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core"   % "2.6.2",
  // Use the "provided" scope instead when the "compile-internal" scope is not supported in your build tool
  "com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "2.6.2" % "compile-internal"
)

Here is a code snippet to parse your input and print parsed data:

import com.github.plokhotnyuk.jsoniter_scala.macros._
import com.github.plokhotnyuk.jsoniter_scala.core._

case class Metadata(@named("HIVE_TYPE_STRING") hive_type_string: String)

case class Field(name: String, @named("type") typeField: String, nullable: Boolean, metadata: Metadata)

case class StructTable(@named("type") typeField: String, fields: Seq[Field])

implicit val codec: JsonValueCodec[StructTable] = JsonCodecMaker.make

val json_struct = """{ "type":"struct", "fields":[ { "name":"code_role", "type":"string", "nullable":true, "metadata":{ "HIVE_TYPE_STRING":"string" } }, { "name":"libelle_role", "type":"string", "nullable":true, "metadata":{ "HIVE_TYPE_STRING":"string" } } ] }""";
val struct = readFromString(json_struct)

println(struct)

The expected output is:

StructTable(struct,List(Field(code_role,string,true,Metadata(string)), Field(libelle_role,string,true,Metadata(string))))

Also you can run it online with Scastie here.