It's unlikely that there will be a solution here that will satisfy every user of the json package, since the problem is that elisp and json have differing semantics. In Lisp, the empty list and the lack of a value (nil) are the same thing. In Javascript (and therefore JSON), the empty array, the "empty" object, the boolean false value, and a lack of a value are three different things. Any mapping between Lisp and Javascript will thus be a matter of compromises.
I recommend defining some advice which changes how json-encode works; just test to see if the object argument is nil and return what you want:
(defadvice json-encode (around encode-nil-as-json-empty-object activate)
(if (null object)
(setq ad-return-value "{}")
ad-do-it))
This will work in the normal recursive case, as the advice will modify the definition of json-encode; the recursive calls will naturally call the modified code.