parseMessage {Proc4} | R Documentation |
The parseMessage
function is a parser to use with the
getOneRec
and getManyRecs
database query
functions. This function will convert the documents fetched from the
database into P4Message
objects. The function
parseData
is a helper function for parsing the data
field of the P4Message
object, and unparseData
is its
inverse.
parseMessage(rec) cleanMessageJlist(rec) parseData(messData) parseSimpleData(messData) unparseData(data, serialize=TRUE)
rec |
A named list containing JSON data. |
messData |
A named list containing JSON data. |
data |
An R object to be serialized. |
serialize |
A logical flag. If true,
|
The $iterator()
method of the mongo
object returns a list containing the fields of the JSON object with a
name=value format. This is the rec
argument.
The parseMessage
function takes the fields of the JSON object
and uses them to populate a corresponding
P4Message
object. Usually, some cleaning is done
first (e.g., to check the argument types and insert default values).
The function cleanMessageJlist
does that cleaning for the
common fields of the P4Message
object, so
subclasses P4Message
can inheret the parsing for the commond
message fields.
The data
field needs extra care as it could contain arbitrary R
objects. There are two strategies for handling the data field.
First, use serializeJSON
to turn the data field
into a slob (string large object), and
unserializeJSON
to decode it. This strategy
should cover most special cases, but does not result in easily edited
JSON output. Second, recursively apply unboxer
and use the function parseSimpleMessage
to undo the coding.
This results in output which should be more human readable, but does
not handle objects (either S3 or S4). It also may fail on more
complex list structures.
The function parseMessage
returns a
P4Message
object populated with fields from the
rec
argument. The function cleanMessageJlist
returns
the cleaned rec
argument.
The function unparseData
returns a JSON string representing the
data. The functions parseData
and parseSimpleData
return a
list containing the data.
I hit the barrier pretty quickly with trying to unparse the data manually. In particular, it was impossible to tell the difference between a list of integers and a vector of integers (or any other storage type). So, I went with the serialize solution.
The downside of the serial solution is that it stores the data field as a slob. This means that data values cannot be indexed. If this becomes a problem, a more complex implementation may be needed.
Russell Almond
as.jlist
, getOneRec
,
getManyRecs
, P4Message
mongo
,
serializeJSON
,
unserializeJSON
m1 <- P4Message("Fred","Task1","PP","Task Done", details=list("Selection"="B")) m2 <- P4Message("Fred","Task1","EI","New Obs", details=list("isCorrect"=TRUE,"Selection"="B")) m3 <- P4Message("Fred","Task1","EA","New Stats", details=list("score"=1,"theta"=0.12345,"noitems"=1)) ev1 <- P4Message("Phred","Level 1","PP","Task Done", timestamp=as.POSIXct("2018-12-21 00:01:01"), details=list("list"=list("one"=1,"two"=1:2),"vector"=(1:3))) m1a <- parseMessage(ununboxer(as.jlist(m1,attributes(m1)))) m2a <- parseMessage(ununboxer(as.jlist(m2,attributes(m2)))) m3a <- parseMessage(ununboxer(as.jlist(m3,attributes(m3)))) ev1a <- parseMessage(ununboxer(as.jlist(ev1,attributes(ev1)))) stopifnot(all.equal(m1,m1a), all.equal(m2,m2a), all.equal(m3,m3a), all.equal(ev1,ev1a)) ## Not run: #Requires test DB setup. testcol <- mongo("Messages", url="mongodb://test:secret@127.0.0.1:27017/test") ## Mongodb is the protocol ## user=test, password =secret ## Host = 127.0.0.1 -- localhost ## Port = 27017 -- Mongo default ## db = test ## collection = Messages testcol$remove('{}') ## Clear everything for test. m1 <- saveRec(m1,testcol) m2 <- saveRec(m2,testcol) m3 <- saveRec(m3,testcol) ev1 <- saveRec(ev1,testcol) m1 <- saveRec(m1,testcol) m1b <- getOneRec(buildJQuery("_id"=c("oid"=m1@"_id")),testcol,parseMessage) stopifnot(all.equal(m1,m1b)) m23 <- getManyRecs(buildJQuery("uid"="Fred",sender=c("EI","EA")), testcol,parseMessage) stopifnot(length(m23)==2L) ev1b <- getOneRec(buildJQuery("uid"="Phred"), testcol,parseMessage) stopifnot(all.equal(ev1,ev1b)) ## End(Not run)