Most classes need nothing here: an S3, S4 or S7 object is a base type
plus attributes, so json_write() records it without help. A class
whose instances hold something outside that model — a connection opened
by initialize, a handle to a running process, a reference that has to
be recorded as a key rather than a value — supplies a method for this
pair instead, modeled on the __getstate__ and __setstate__ protocol
of Python's pickle.
Details
A json_state() method returns a plain list of what to persist, and is
free to leave out anything that can be recomputed. The document records
that list next to the classes the object dispatches on, which for an S4
object or a reference class instance is its inheritance chain rather than
the concrete class alone. On the way back, json_revive() dispatches on
the recorded classes through an empty object carrying them, so a method
signature always starts with the class token rather than the object being
rebuilt, and a method registered on a superclass is reached both ways.
Methods for the class generators of both R6 and S7 ship with the
package and follow the same protocol. An R6 instance has no method,
and writing one is refused rather than guessed at; see r6_state() for
why, and for the pair a class author opts in with. A reference class
instance is refused on the same grounds. A method on the concrete
class settles it, as does one on any class between that and
envRefClass, which is where the refusal itself sits. The generator
that makes one is refused outright, since a walk into it reaches the
internals of the methods package rather than the class.
Examples
handle <- structure(list(path = "/tmp/log", con = "a live connection"),
class = "file_handle")
json_state.file_handle <- function(x) list(path = x$path)
json_revive.file_handle <- function(class, state) {
structure(list(path = state$path, con = NULL), class = "file_handle")
}
json_write_str(handle)
#> [1] "{\"~a\":{\"class\":\"file_handle\"},\"~v\":{\"path\":\"/tmp/log\",\"con\":\"a live connection\"}}"
json_read_str(json_write_str(handle))
#> $path
#> [1] "/tmp/log"
#>
#> $con
#> [1] "a live connection"
#>
#> attr(,"class")
#> [1] "file_handle"