Nested and delegating object-graph utilities.
var dotted = require('dotted');
// ohai, some tweets
var tweets = {
"requested_at": "Thu Oct 09 09:50:20 +0000 2014",
"items": [
{
"id": 516626496845131800,
"created_at": "Mon Sep 29 16:32:09 +0000 2014",
"text": "the other thing that happens when you do something for 10,000 hours is you develop a really refined hatred for it",
"user": {
"id": 16142493,
"screen_name": "me_irl",
"name": "the government man"
},
"retweet_count": 55,
"favorite_count": 79
}, {
"id": 516596160208076800,
"created_at": "Mon Sep 29 14:31:37 +0000 2014",
"text": "It's Piketty week, and someone in my Economic Justice class is wearing a 'r>g' shirt. <3",
"user": {
"id": 19530289,
"screen_name": "PennyRed",
"name": "Laurie Penny"
},
"retweet_count": 6,
"favorite_count": 18
}, {
"id": 516438947367358460,
"created_at": "Mon Sep 29 04:06:54 +0000 2014",
"text": "finding out an “indie” site has VC funding is the Internet version of learning your Marxist urban poet friend has a trust fund",
"user": {
"id": 55525953,
"screen_name": "Pinboard",
"name": "Pinboard"
},
"retweet_count": 190,
"favorite_count": 206
}
],
"notes": {
"cRaZy.note": "completely unreasonable"
}
};
// funny stuff.
// but we have some srs bsns to attend to.
dotted.getNested(tweets, 'items.1.user.screen_name') // => 'PennyRed'
// Array indices are fine, as all keys are strings in JS
dotted.setNested(tweets, 'flags.reviewed', true)
// No error is thrown, but...
dotted.getNested(tweets, 'flags.reviewed') // => undefined
// The fact that `flags` doesn't exist prevents `reviewed` from being set.
// The `ensure` option will fix it.
dotted.setNested(tweets, 'flags.reviewed', 'twice!', { ensure:true })
dotted.getNested(tweets, 'flags.reviewed') // => 'twice!'
// Ahh, much better.
// Note dotted also accepts Arrays in place of dotted keys -- this helps us
// deal with cRaZy keys with dots in them:
dotted.getNested(tweets, ['notes', 'cRaZy.note']) // => 'completely unreasonable'
Word.
For usage in node.js, install it via npm:
npm install dotted
For the client side, I'm a fan of [browserify][browserify] to get my require
on.
When there isn't a require
about, dotted
will simply install itself at window.dotted
.
It's up to you how you get it on the page -- you can download a dotted.js dist (old school);
or install via a random client-side package-manager (crazy):
bower install dotted
component install dsc/dotted
dotted
presently depends on a _
library, so get lodash (or underscore)
on the page as well. You can mix dotted
into _
, if you wish, for convenience and chaining:
var _ = require('lodash');
_.mixin(dotted);
This dependency is ugly, but for now dotted
will attempt to require a _
library if it can,
and fall back to window._
/ globals._
. It yells if both fail. Anyway, even once that's
cleaned up, dotted
will still play nicely with others -- as a mixin and standalone.
Many accessor functions take an options object with common fields. The sub-object
delegation options (getter
, setter
, and deleter
) are used to specify where
to look for the specific accessor method on a custom sub-object when performing
that operation. (Functions that do not use that operation will ignore these
options, so you're welcome to specify them everywhere just to be safe.)
name | type | default | description |
---|---|---|---|
getter | String |
"get" |
Name of the sub-object getter method to delegate to (if it exists). |
setter | String |
"set" |
Name of the sub-object setter method to delegate to (if it exists). |
deleter | String |
"delete" |
Name of the sub-object deleter method to delegate to (if it exists). |
ensure | Boolean |
false |
If true, intermediate keys that are null or undefined will be filled in with a new empty object {} , ensuring the get will return valid metadata. |
Gets the value at key
from the object if present, returning def
otherwise.
Puts a given value to key
on the given target object. If an object is supplied as key
instead of a String,
each key-value pair on that object will be put to the target object. In this case, omit value
. Returns the
target object.
Deletes key
from the target object, returning whatever value was present prior to being removed.
These methods perform nested accessor operations, delegating like their non-nested counterparts to the target object when an instance method is found matching the operation.
Searches a hierarchical object for a given subkey specified in dotted-property syntax, returning the value
if found, and def
otherwise.
Searches a hierarchical object for a given subkey specified in dotted-property syntax, setting it with the provided value if found.
Searches a hierarchical object for a potentially-nested key and removes it, returning whatever value was previously there prior to removal.
Aliases: unsetNested
.
[Private] Searches a hierarchical object for a given subkey (specified in dotted-property syntax),
respecting sub-object accessor-methods (e.g., 'get', 'set') if they exist. If found, returns an object
of the form { key: Qualified key name, obj: Parent object of key, val: Value at obj[key], opts: Options }
,
and otherwise undefined
.
Find a bug or want to contribute? Open a ticket (or fork the source!) on github. You're also welcome to send me email at dsc@less.ly.
--
dotted
was written by David Schoonover; it is open-source software and
freely available under the MIT License.
-
This project is written in Coco, a dialect of CoffeeScript -- both of which compile down to plain JavaScript. Coco and Coffee are quite similar, except for a few things. (Things which, imo, make Coco vastly more pleasant to work in). If you can read JavaScript (or Ruby, really), you'll find Coco/Coffee familiar.
(I refer to the CoffeeScript docs for the syntax, and I find the comparison page to be the best reference for Coco.)
-
Coco requires compilation before it'll run in the browser (though node can run it directly --
#!/usr/bin/env coco
will work as a shebang as well). I wrote request middleware that recompiles stale files on demand, and it is pretty cool.