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.