Refactor some helper code in JSON.Encode

Instead of adding encode support for maps, forcing users to upgrade to v0.13 this patch makes it trivial to add support for maps later.

This also makes it easier to define slightly more efficient helpers.

There is one slight semantics change: `{{"A", "B"}, {"C", "D"}}` won't get
encoded as `{"A": "B", "C", "D"}` but as `[["A", "B"], ["C", "D"]]` because a
tuple now gets treated as a non-keyword list instead of a possibly-keyword list.