Home > OS >  Updating a Value inside a Map[String, Map] with scala
Updating a Value inside a Map[String, Map] with scala

Time:12-01

I am trying to read some DynamoDb data and update them using spark/scala. I am reading the data in Json like this:

{
    "2021-11-24": {
        "Execution_Steps": {
            "Step_1": "OK",
            "Step_2": "RUNNING"
        },
        "status": "RUNNING",
        "start_date": "2021-11-25 00:00:00"
    },
    "2021-11-20": {
        "end_date": "2021-11-25 01:00:00",
        "status": "OK",
        "start_date": "2021-11-25 00:00:00"
    }
}

Using jackson I could serialize it to Maps val dataMap = mapper.readValue(jsonData, classOf[Map[String, String]])

So i got this map: Map(2021-11-20 -> Map(end_date -> 2021-11-25 01:00:00, status -> OK, start_date -> 2021-11-25 00:00:00), 2021-11-24 -> Map(Execution_Steps -> Map(Step_2-> RUNNING, Step_1-> OK), status -> RUNNING, start_date -> 2021-11-25 00:00:00))

How can I update the Map "2021-11-24"."Execution_Steps"."Step_2" to OK instead of Running?

Thanks!

CodePudding user response:

I solved the problem with gatear's help, Instead of read data like this: val dataMap = mapper.readValue(jsonData, classOf[Map[String, String]])

I read in a ObjectNode: val dataMap = mapper.readTree(jsonData).asInstanceOf[ObjectNode]

Then I was able to update using the command: dataMap.get("2021-11-24").asInstanceOf[ObjectNode].get("Execution_Steps").asInstanceOf[ObjectNode].put("Step_2", "OK")

CodePudding user response:

Well assuming your starting point:

import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper}
import com.fasterxml.jackson.databind.node.ObjectNode

val json = "{\n    \"2021-11-24\": {\n        \"Execution_Steps\": {\n            \"Step_1\": \"OK\",\n            \"Step_2\": \"RUNNING\"\n        },\n        \"status\": \"RUNNING\",\n        \"start_date\": \"2021-11-25 00:00:00\"\n    },\n    \"2021-11-20\": {\n        \"end_date\": \"2021-11-25 01:00:00\",\n        \"status\": \"OK\",\n        \"start_date\": \"2021-11-25 00:00:00\"\n    }\n}"

You can work with the JsonNode directly and go into a Map[String,String] as a final step

val objectMapper = new ObjectMapper()
val jsonNode = objectMapper.readTree(json)

def update(objectNode: JsonNode): JsonNode = {
  jsonNode
    .get("2021-11-24")
    .get("Execution_Steps")
    .asInstanceOf[ObjectNode]
    .put("Step_2", "OK")
  
  objectNode
}

val updated = 
  update(jsonNode)

objectMapper
  .treeToValue(updated, classOf[java.util.Map[String,String]])

Note:get may return null. Maybe use Option?

This API doesn't really go well with Scala's immutability philosophy.

  • Related