# Advanced Customization

    library(RJSONIO)

`RJSONIO` exposes customization points for parser events, string conversion, JavaScript variable output, and S4 serialization.

## Parser handlers

`basicJSONHandler()` returns an object with `update()` and `value()` functions. The parser calls `update()` for each JSON token.

    handler <- basicJSONHandler()
    fromJSON("[1, 3, 10, 19]", handler$update)
    #> NULL

    handler$value()
    #> [[1]]
    #> [1] 1
    #>
    #> [[2]]
    #> [1] 3
    #>
    #> [[3]]
    #> [1] 10
    #>
    #> [[4]]
    #> [1] 19

A callback can also collect token names directly.

    events <- character()

    fromJSON('{"a": 1, "b": "x"}', function(type, value) {
      events <<- c(events, names(type))
      TRUE
    })
    #> NULL

    unique(events)
    #> [1] "OBJECT_BEGIN" "KEY"          "INTEGER"      "STRING"       "OBJECT_END"

## String callbacks

Use `stringFun` to transform strings while parsing.

    fromJSON('[1, "abc", "xyz"]',
             stringFun = function(value) sprintf("parsed_%s", value))
    #> [[1]]
    #> [1] 1
    #>
    #> [[2]]
    #> [1] "parsed_abc"
    #>
    #> [[3]]
    #> [1] "parsed_xyz"

    fromJSON('["1", "2.3", "3.1415"]',
             stringFun = function(value) as.numeric(value))
    #> [1] 1.0000 2.3000 3.1415

## JavaScript variable output

`asJSVars()` formats named values as JavaScript-style assignments and returns the generated text invisibly.

    js <- asJSVars(a = 1:3, b = "x")
    cat(js)
    #> a = [ 1, 2, 3 ] ;
    #>
    #> b = [ "x" ] ;

Type annotations can be requested for common scalar values.

    cat(asJSVars(.vars = list(count = 3L, label = "x"), types = TRUE))
    #> count : int = [ 3 ] ;
    #>
    #> label : String = [ "x" ] ;

## S4 objects

S4 objects are serialized by their slots unless a more specific method is defined.

    setClass("RJSONIOVignetteClass",
             representation(id = "integer", label = "character"))

    object <- new("RJSONIOVignetteClass", id = 1L, label = "example")
    cat(toJSON(object))
    #> { "id": 1,"label": "example" }

Packages can define class-specific `toJSON()` methods when a different JSON shape is needed.

    setClass("RJSONIOPoint", representation(x = "numeric", y = "numeric"))

    setMethod("toJSON", "RJSONIOPoint",
              function(x, container = TRUE, collapse = "\n", ...,
                       .level = 1L, .withNames = TRUE, .na = "null",
                       .escapeEscapes = TRUE, pretty = FALSE, asIs = NA,
                       .inf = " Infinity") {
                toJSON(list(x = x@x, y = x@y),
                       container = container, collapse = collapse, ...,
                       .level = .level, .withNames = .withNames, .na = .na,
                       .escapeEscapes = .escapeEscapes, pretty = pretty,
                       asIs = asIs, .inf = .inf)
              })

    point <- new("RJSONIOPoint", x = 1, y = 2)
    fromJSON(toJSON(point))
    #> [1] 1 2