At the heart of the problem is that JSON combines floating point types and integer types - they are not distinguished using a type tag in JSON format. Therefore, we present all numeric types in JSON through Rationals, under the hood.
JSON Double, Int .., Rational - , :
instance JSON Rational where
showJSON r = JSRational True r
readJSON (JSRational _ r) = return r