duckertito
duckertito

Reputation: 3645

com.fasterxml.jackson.databind.JsonMappingException

I use JacksMapper to parse JSON strings to Map[String,String]:

  def parseJSON(line: String): Map[String, String] = {
    JacksMapper.readValue[Map[String, String]](line)
  }

For some JSON strings it throws the error:

com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token

In particular it happens with this string:

{"id":"123","name":"visited","category":"abc","x_ids":["220"]}

I assume that the problem is with "x_ids":["220"], while I expect the result as Map[String,String]. So, in this case I would be interested to convert arrays to strings like "x_ids"->"220,230". How can I do it flexibly so that the solution would be adaptable to other possible fields that might be arrays in some cases?

EDIT: In my case I never have complex arrays that should be parsed with a static class. Only arrays of numbers or strings.

Upvotes: 0

Views: 1327

Answers (2)

StaxMan
StaxMan

Reputation: 116620

This is because you claim all values are Strings, but x_ids is a JSON Array, not JSON String. Two ways to go about it:

  1. Declare value type as java.lang.Object, in which case you get String and Lists
  2. Enable DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS in which case JSON Array with one (and only one!) element may be "unwrapped" to match expected type -- not 100% sure it works here, but in theory should

Upvotes: 0

Alban Dericbourg
Alban Dericbourg

Reputation: 1634

You could do it in two steps:

  1. Parse JSON without caring of the value type
  2. Map the values and transform them if needed

That could give something like:

def parseJSON(line: String): Map[String, String] = {
  JacksMapper.readValue[Map[String, Any]](line)
    .mapValues {
      case array: Iterable[Any] => array.mkString(", ")
      case anyValue: Any        => anyValue.toString
    }
}

Upvotes: 1

Related Questions