You have to worry about json having a floating point number or an integer that is too large to be represented in a Word32, although you could also just let it overflow if you don't care too much. There's probably an easier way to do this, but this is what I came up with.
instance FromJSON CUid where
parseJSON (Number n) = do
case floatingOrInteger n of
Right i | inrange i -> return . CUid . fromIntegral $ i
-- not an integer, or not in range
_ -> mempty
where
inrange :: Integer -> Bool
inrange i = fromIntegral i >= (minBound @Word32) &&
fromIntegral i <= (maxBound @Word32)
-- not a number
parseJSON _ = mempty