paul
paul

Reputation: 13481

Jackson deserialize with Generics

I´m trying to deserialize a json into scala class, that contains a Collection of types Aclass,Bclass or Cclass

class Results[M](results:util.ArrayList[M]) {

  def getResults:util.ArrayList[M]=results

  def this() {
    this(new util.ArrayList())
  }
}

The Json looks like:

{ "results":[{"a":1},{"a":1}]} 

or

{ "results":[{"b":1},{"b":1}]} 

or

{ "results":[{"b":1},{"b":1}]} 

Here my object mapper

  val mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

And here how I deserialize a json of class type Aclass

val results = mapper.readValue(json, classOf[Results[Aclass]])

The problem is that results, return a ArrayList where every element instead to be an instance of Aclass, is a LinkedHashMap.

If I change the code instead to use generic I make it explicit in the type

class Results[Aclass](results:util.ArrayList[Aclass]) {

  def getResults:util.ArrayList[Aclass]=results

  def this() {
    this(new util.ArrayList())
  }
}

It works and return an class with result of array of Aclass elements.

What I´m doing wrong here?. I think it´s a bug in the library

Regards.

Upvotes: 0

Views: 640

Answers (1)

ondrc
ondrc

Reputation: 106

The reason is that java.lang.Class does not hold information about generic parameters. The value of classOf[Result[Aclass]] is java.lang.Class. It does not have information about the type parameter Aclass. It represents only the Results class.

The mapper does what you ask for: gives you Results of whatever and the best whatever for it is a map.

To solve it, use readValue method that takes JavaType instead. JavaType can be created using TypeFactory:

val results:Results[Aclass] = mapper.readValue(json, mapper.getTypeFactory()
        .constructParametricType(classOf[Results[_]], classOf[Aclass]))

Upvotes: 3

Related Questions