0
votes

I'm writing server that executes any select query on my db and returns json. I've done most of that task but I stuck with parsing nullable column to string.

val result = SQL("SELECT * FROM Table limit 5;")().map(_.asList.map({_.toString})).toList
val jsonResp = Json.toJson(result)

And that generates if the column could have null value string Some(123) instead of 123. I tried with match but I failed with compose that command. Maybe you had some similar problem and you know how to deal with that kind of response?

Edit: I made some progress by adding pattern matching:

    val result = SQL(query)()
      .map(_.asList.map(
    {
      case Some(s) => s.toString
      case None => ""
      case v => v.toString
    }
    )).toList

but I'm not sure is it good way to solve that problem. Still waiting for ideas

2
What you are doing is rendering null column values as empty strings. An empty string is not the same as null, even though some databases map it that way. Similarly, a nullable integer column will also render as an empty string. This may not meet your needs for type safety in JSON. - Bob Dalgleish

2 Answers

1
votes

Anorm is supporting nullable column as optional value.

There you return row as a list of raw value. It would be better to use the parser API to indicate how to extract properly values. E.g.

SQL("SELECT a, b, c ...").as(get[Option[String]]("a") ~ int("b") ~ str("c) map { case a ~ b ~ c => MyClass(a, b, c) }.*)

Returns SQL results as list of MyClass, with properties being in order Option[String], Int and String.

Anorm documentation has plenty of other examples.

-1
votes

It would probably be best to map optional entries in the database to optional fields in the json; most scala json libraries will render a field with Option type appropriately. It also seems odd that you would want to render an integer value as a string for json - json has a perfectly good numeric type for integers.

If you definitely want to convert an Option[Int] to a string in this fashion, the clearest way is probably o.map(_.toString).getOrElse(""); you could therefore write _.asList.map{_.map{_.toString}.getOrElse("")} rather than your pattern-match. I don't know the specific SQL library well enough to know whether the results are statically known to be of type Option or not; if the values are of type Any then you probably do need to match options and non-options the way you have.