I've got deeply nested JSON parsers (using json4s.jackson
) that I'm trying to simplify using case classes.
My problem is... some of the fields start with numbers, but scala cannot have an arg name that starts with a numeric character.
Example:
import org.json4s.jackson.JsonMethods._
import org.json4s._
implicit val formats = DefaultFormats
val jsonStr = """{"5gLog":{"i":99}}""" // <--- note the field "5gLog"
val jval = parse(jsonStr)
case class Raw5gLog(i: Int)
val raw5gLog = (jval \ "5gLog").extract[Raw5gLog]
This works. But what I need to do, because these fields are nested deep within the JSON... is something like this...
val jsonStr = """{"xgLog":{"i":99}}"""
val jval = parse(jsonStr)
case class RawRecord(xgLog: Raw5gLog)
val rawRecord = jval.extract[RawRecord]
This would work... if the fields were named like xgLog
, but the fields are actually named like 5gLog
as above, and I can't give an arg name to a class like 5gLog
...
case class RawRecord(5gLog: Raw5gLog)
// error: Invalid literal number
I thought about something like
parse(jsonStr.replace("\"5g", "\"fiveg"))
But there's real data, beyond the field names, in the JSON that can be impacted.
The best solution I can figure is to add extra apply methods to the affected case classes...
case class RawRecord(fivegLog: Raw5gLog)
object RawRecord {
def apply(jval: JValue): RawRecord =
RawRecord( (jval \ "5gLog").extract[Raw5gLog] )
}
val rawRecord = RawRecord(jval)
But I feel like every time I make some structurally different workaround like this for an edge case, it's always the beginning of my code turning into a mess. I could give every case class a new apply method and use it for everything, but it seems like a lot of extra code for a small subset of the data.
Is there a better way?
Scala can use any string as a variable name, but you may have to quote it with backticks:
case class RawRecord(`5gLog`: Raw5gLog)
You also need to do this if you have a field called type
or any other reserved word. This is how -
can be a function name, for example.