Hi all (again),
As part of writing the port (and adaptation to use Zinc and NeoJSON),
a CouchDB JSON-REST API, now I find something I don't know how to
solve using NeoJSON mappings.
All objects you store in CouchDB at a particular URI are saved as
"Documents", so if you save a dictionary with keys "name", "height",
"c" to "/people/1234" , when you query "people/1234" you get the keys
of the saved dictionary PLUS to extra keys called _id and _rev.
Then when you query (GET) back the document you get a JSON like this:
{"_id": ..., "_rev": ..., "name": ..., "height":...,}
My Idea is that I can wrap any object serializable as JSON within
aDocument, but then if I define CouchDocument class>>#neoJsonMapping:
mapper as:
mapper for: self do: [ :mapping |
mapping mapAccessor: #id to: '_id'.
mapping mapAccessor: #revision to: '_rev'.
mapping mapAccessor: #class to: '_class'
].
I have no way to "flatten"/"merge" anObject within aDocument.
I would expect something like
mapper for: self do: [ :mapping |
mapping mapAccessor: #id to: '_id'.
mapping mapAccessor: #revision to: '_rev'.
mapping mapAccessor: #class to: '_class'
mapping embed: [:object | object whatToEmbed]
].
Of course this is awkward, because if I need to read it back, the
"extraction" of the embeded properties needs to know which belongs to
which and more importantly , what to instantiate!
Of course I can do it manually without using NeoJSON (It's already
being done [1]) , but I like when different libraries things fit
naturally together :)
Am I stretching it too much? :)
Regards,
[1] Currently the writing is done manually and the refresh (which is
also a GET) does the following:
CouchDocument>>#refresh
" Update this Document to the latest revision "
| response |
response := self information. "response is a Dictionary"
revision := response at: '_rev'.
object := response couchToObject.
^response
And here happens the magic, it searchs for a "_class" key which if
present will use to instantiate the object "wrapped" by the document.
Dictionary>>couchToObject
| class object |
self removeKey: '_id' ifAbsent: [].
self removeKey: '_rev' ifAbsent: [].
self keysAndValuesDo: [:key :value | self at: key put: value couchToObject].
class := (self at: '_class' ifAbsent: [^self]) asSymbol asClass.
object := class basicNew.
object jsonInstanceVariableNames keysAndValuesDo: [:index :key |
self at: key ifPresent: [:value | object instVarAt: index put: value]].
^object
#jsonInstanceVariableNames is another level of "mapping" here, that
defined what to map from the Document response.
Esteban A. Maringolo