0
votes

I have a JSON string that I need to process and I am mapping it in the following manner:

val jsonMap = mapper.readValue[Map[String, Object]](jsonString)

My jsonMap contains the following value:

Map(k1 -> List(Map(k2 -> v2), Map(k3 -> v3))

The desired value for newJsonMap is:

 Map(k1 -> Map(k2 -> v2))

So in a nutshell, I want to convert the value of the k1 key from a List to a Map. I first started to implement according to this question: Scala - Flatten a List of Maps to Map

But then I realized that I was dealing with different datatypes, in this case Map[String, Object] which means I can't perform operations such as using the scala in-built flatten method to lists.

Is there any way I can convert this Map into a Scala Map so I can apply the necessary transformations to the JSON? Any thoughts on how I should proceed?

Thanks in advance.

1
Which json library are you using? You must use that library or are you open to other options? What should be the type of the output? Can you give us an example json? Ate you sure you want a map of maps? Do you know the format you are parsing, if so why not defining some case classes that properly represent your model and parse your json into that?Luis Miguel Mejía Suárez
@LuisMiguelMejíaSuárez, thanks for your help first of all. I am using jackson module to read the JSON into a Map[String, Object]. The main goal was to convert a json list into a json element (ie, replace "[ ]" for "{ }"). Example: json = { k1 = [ k2 = { ... } .. ] .. } into { k1 = { k2 = { ... } .. } .. }. In this particular case, since I only need to do this conversion for an expected specific case the solution I found fits the problem. Thanks :)ruifgmonteiro

1 Answers

1
votes

The simple answer is to do this

val jsonMap = mapper.readValue[Map[String, List[Map[String, String]]]](jsonString)

and then use the answer from the previous question.

If you want to do it by hand, something like this should work:

val map: Map[String, Map[String, String]] =
  jsonMap.collect {
    case (k, v: List[_]) =>
      val list: List[Map[String, String]] =
        v.collect {
          case m: Map[_, _] =>
            m.collect {
              case (k: String, v: String) =>
                k -> v
            }
        }
      k -> list.headOption.getOrElse(Map.empty)
  }

This will ignore any elements in Object that are not the required type. Nested collect expressions are required because type erasure prevents matching on a nested type in one operation.

This is assuming that you want the head of the List[Map] inside the Object, but it should be clear how to change this to a different transformation.