Accessing fields with problematic names

51 views
Skip to first unread message

Jim Newsham

unread,
Feb 6, 2015, 4:45:15 PM2/6/15
to raptur...@googlegroups.com

One of my colleagues is trying to extract data from a JSON string where some objects have fields named "wait".  Since "wait" is defined on AnyRef (java.lang.Object), this is problematic.

Example 1:  Extraction to a case class.  My colleague discovered that using .as[T], rapture-json will extract a json object to a case class if the json object has fields whose names match the case class' field names.  So he tried to use a case class such as the following:

case class Datum(id: String, wait: Long, ...)

This case class cannot compile due to a name collision on the "wait" field.  I see that rapture has support for adding a field to a json object (using "+"), but if there were an easy way to rename a field, that would help here.

Example 2: Using rapture-json's accessor notation.  Trying to access the field using json's dynamic accessor support, one would call:

json.datum.wait

This fails at runtime with an IllegalMonitorStateException, which indicates that the wait call is being resolved to Object.wait().  If there were a way to access a field by name (given as a string), that would help here.  Something like:  json.datum.getFieldValue("wait").

Any pointers would be appreciated.  Thanks!
Jim


Jon Pretty

unread,
Feb 6, 2015, 6:47:49 PM2/6/15
to raptur...@googlegroups.com
Hi Jim,

Thanks for the clear questions and examples!

For the second problem, the current source version (as-yet unreleased) supports \-style access of object keys using strings, so

  json.datum.wait

could instead be written as

  json \ "datum" \ "wait"

which would avoid the problem with methods already defined on `AnyRef`, like `wait`, `toString`, `notify` and `equals`. Luckily there aren't many of them, but they can catch you out when you're not expecting them. All the non-dynamic methods defined on `Json` types are either symbolic, or begin with a `$` (in which case, they're only intended for internal usage) so as not to pollute the namespace.

If you're using version 1.1.0, for now, unfortunately, you'll have to use the `selectDynamic` method instead of `\`, like this:

  json.datum.selectDynamic("wait")

This is basically what the dynamic accesses get translated to by the compiler.


Your first example is not something I had considered before, so it's an interesting challenge. The "obvious" answer is to define your own extractor, though this requires a lot of boilerplate. Here's an example for your Datum class, assuming that we rename `wait` to something else:

  implicit val datumExtractor: Extractor[Datum, Json] =
    Json.extractor[Json].map { j =>
      Datum(j.id.as[String], j.selectDynamic("wait").as[Long], ...)
    }

This extractor should then take precedence over the default one, and you shouldn't get the problem with `wait`.

Another solution, as you suggested, was to rename a field. I was going to suggest that you just add the new element with `+` and remove the old with `-`. But I've just spotted that `-` doesn't exist, which is an oversight (https://github.com/propensive/rapture-json/issues/42). That doesn't actually matter, because case class extraction will just ignore any unused fields, so you should be able to write:

  val datum = (json + (_.waitVal, json.selectDynamic("wait"))).as[Datum]

and that should work.

I'm a little reluctant to either complicate the macro with rename functionality (in particular, I'd like to avoid annotations as a possible solution to this), and there doesn't seem to be a particularly clean way of providing it without introducing further confusion. But I'd be interested to hear how things go with the above workarounds.

Cheers,
Jon

--
You received this message because you are subscribed to the Google Groups "Rapture users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rapture-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Jon Pretty | @propensive

Jim Newsham

unread,
Feb 9, 2015, 2:21:04 PM2/9/15
to raptur...@googlegroups.com

Thanks Jon, your feedback has been really helpful!  

Regards,
Jim
Reply all
Reply to author
Forward
0 new messages