jsonscalajson4s

How to use camelizeKeys with hyphens


I am parsing a json response from a web service which has some fields defined using hyphens. I want to convert these names to mixed case names in my scala case class. I thought to use the camelizeKeys stipulation but it doesn't seem to work. So for example say I have a json response like:

{"offset":0,"total":359,"per-page":20}

to be converted to:

case class Response(offset: Int, total: Int, perPage: Int)

and I do:

parse(str).camelizeKeys.extract[Response]

I get the error:

Ex: org.json4s.package$MappingException: No usable value for perPage Did not find value which can be converted into int


Solution

  • A work around is to replace all occurrences of the hyphen with an underscore before parsing the text. So one could do the following:

    parse(str.replaceAll("([a-z])-([a-z])", "$1_$2")).camelizeKeys.extract[Response] 
    

    But this solution is limited as with complicated data structures it may not work; you could end up corrupting the data returned if any field values contains such a pattern. So a more complete solution was to write my own replaceAll function:

    def replaceAll(str: String, regex: String)(f: String => String) = {
        val pattern = regex.r
        val (s, i) = (("", 0) /: pattern.findAllMatchIn(str)) { case ((s, i), m) =>
            (s + str.substring(i, m.start) + f(m.toString), m.end)
        }
        s + str.substring(i)
    }
    

    and apply it to my json string thus:

    replaceAll(str, "\"[0-9a-z\\-]*\":")(_.replace('-', '_'))