Serialize events both to and from JSON (rather than just to)

This requires every field of every event to be completely reconstructible from its
JSON representation. This commit may contain incomplete state.