diff --git a/htools/Ganeti/HTools/JSON.hs b/htools/Ganeti/HTools/JSON.hs index b2f40fb458c81a61db47a5e267dd261fbd4b2b69..2667f80a3a0b984fcf30a44cd11bfb14a929ba24 100644 --- a/htools/Ganeti/HTools/JSON.hs +++ b/htools/Ganeti/HTools/JSON.hs @@ -84,15 +84,26 @@ fromObj o k = k (show (map fst o)) Just val -> fromKeyValue k val --- | Reads the value of an optional key in a JSON object. +-- | Reads the value of an optional key in a JSON object. Missing +-- keys, or keys that have a \'null\' value, will be returned as +-- 'Nothing', otherwise we attempt deserialisation and return a 'Just' +-- value. maybeFromObj :: (J.JSON a, Monad m) => JSRecord -> String -> m (Maybe a) maybeFromObj o k = case lookup k o of Nothing -> return Nothing + -- a optional key with value JSNull is the same as missing, since + -- we can't convert it meaningfully anyway to a Haskell type, and + -- the Python code can emit 'null' for optional values (depending + -- on usage), and finally our encoding rules treat 'null' values + -- as 'missing' + Just J.JSNull -> return Nothing Just val -> liftM Just (fromKeyValue k val) --- | Reads the value of a key in a JSON object with a default if missing. +-- | Reads the value of a key in a JSON object with a default if +-- missing. Note that both missing keys and keys with value \'null\' +-- will case the default value to be returned. fromObjWithDefault :: (J.JSON a, Monad m) => JSRecord -> String -> a -> m a fromObjWithDefault o k d = liftM (fromMaybe d) $ maybeFromObj o k