I have the following JSON
{
"record1": {
"firstName": "John",
"lastName": "Doe",
"locations": {
"29b2f2295cd74b8cbb53db4379f0d823": "New York"
}
},
"record2": {
"firstName": "Carol",
"lastName": "Rees",
"locations": {
"0055bb74b4984156b821ebbea6937084": "California"
}
},
"record3": {
"firstName": "Colin",
"lastName": "Scott",
"locations": {
"aba67f566fc24f8a8eb3165648ca5e4f": "Toronto",
"b847750c565246638dbc72cb89ead227": "London"
}
}
}
which needs to be transformed to the following using Scala
{
"record1": {
"firstName": "John",
"lastName": "Doe",
"locations": [{
"id" : "29b2f2295cd74b8cbb53db4379f0d823",
"location": "New York"
}]
},
"record2": {
"firstName": "Carol",
"lastName": "Rees",
"locations": [{
"id" : "0055bb74b4984156b821ebbea6937084",
"location": "California"
}]
},
"record3": {
"firstName": "Colin",
"lastName": "Scott",
"locations": [{
"id": "aba67f566fc24f8a8eb3165648ca5e4f",
"location:" : "Toronto"
},
{
"id" : "b847750c565246638dbc72cb89ead227",
"location": "London"
}]
}
}
I am being new to scala, this is what I have so far
case class PersonEntry(firstName: String, lastName: String, locations: Map[String, String])
val jsonMapper = JsonMapper.builder().addModule(DefaultScalaModule).build()
val inputJson: String = "{\n \"record1\": {\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"locations\": {\n \"29b2f2295cd74b8cbb53db4379f0d823\": \"New York\"\n }\n },\n \"record2\": {\n \"firstName\": \"Carol\",\n \"lastName\": \"Rees\",\n \"locations\": {\n \"0055bb74b4984156b821ebbea6937084\": \"California\"\n }\n },\n \"record3\": {\n \"firstName\": \"Colin\",\n \"lastName\": \"Scott\",\n \"locations\": {\n \"aba67f566fc24f8a8eb3165648ca5e4f\": \"Toronto\",\n \"b847750c565246638dbc72cb89ead227\": \"London\"\n }\n }\n}"
val parsedPerson = jsonMapper.readValue(inputJson, classOf[Map[String, Any]])
val personMap: Map[String, PersonEntry] = parsedPerson.mapValues(jsonMapper.convertValue(_, classOf[PersonEntry]))
CodePudding user response:
There are several ways to do it. As you already have written a case class representing the input data, I would:
- create a case class representing the output data
- parse input as input case classes
- map input case class to output case class
- generate JSON for output case classes
If performance matters, you could look to work without parsing to case classes and operate directly on the JSON input but I won't explain this option.
That is, something along the lines of:
case class PersonOutput(firstName: String, lastName: String, locations: Seq[Location])
case class Location(id: String, location: String)
val output: Map[String, PersonOutput] = jsonMapper
.readValue(inputJson, classOf[Map[String, PersonEntry]])
.map { case (key, person) =>
val newLocations = person.locations.map {
case (k, v) => Location(k, v)
}
key -> PersonOutput(person.firstName, person.lastName, newLocations)
}
// Then generate JSON for output