Skip to content
This repository has been archived by the owner on Sep 9, 2020. It is now read-only.

Commit

Permalink
Make to-json work on more inputs. (#578)
Browse files Browse the repository at this point in the history
* Make to-json work on more inputs.

Now also converts:
- vectors,
- keywords,
- dicts with mixed string/keyword keys.
  • Loading branch information
jameshaydon committed Mar 22, 2019
1 parent a505c81 commit ac6e647
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 8 deletions.
7 changes: 6 additions & 1 deletion docs/source/reference.rst
Expand Up @@ -445,7 +445,12 @@ right now, formatted according to ISO 8601.
``to-json``
~~~~~~~~~~~

Returns a JSON formatted string representing the input value.
Returns a JSON formatted string representing the input value. Numbers
are only converted if they have a finite decimal expansion. Strings and
booleans are converted to their JSON counterparts. Keywords are
converted to JSON strings (dropping the initial ':'). Lists and vectors
are converted to JSON arrays. Dicts are converted to JSON objects as
long as all the keys are either strings or keywords.

``uuid!``
~~~~~~~~~
Expand Down
15 changes: 9 additions & 6 deletions src/Radicle/Internal/Core.hs
Expand Up @@ -422,9 +422,9 @@ isAtom _ = Nothing
-- >>> encode $ maybeJson $ Dict $ Map.fromList [(String "foo", String "bar")]
-- "{\"foo\":\"bar\"}"
--
-- This fails for lambdas, since lambdas capture an entire environment
-- (possibly recursively). It also fails for dictionaries with non-string key
-- non-string keys.
-- This fails for lambdas, since lambdas capture an entire environment (possibly
-- recursively). It also fails for dictionaries with non-stringy (string or
-- keyword) keys.
--
-- >>> import Data.Aeson (encode)
-- >>> encode $ maybeJson $ Dict $ Map.fromList [(Number 3, String "bar")]
Expand All @@ -433,17 +433,20 @@ maybeJson :: Value -> Maybe A.Value
maybeJson = \case
Number n -> A.Number <$> hush (Num.isSci n)
String s -> pure $ A.String s
Keyword (Ident i) -> pure $ A.String i
Boolean b -> pure $ A.Bool b
List ls -> toJSON <$> traverse maybeJson ls
Vec xs -> toJSON <$> traverse maybeJson (toList xs)
Dict m -> do
let kvs = Map.toList m
ks <- traverse isStr (fst <$> kvs)
ks <- traverse isStringy (fst <$> kvs)
vs <- traverse maybeJson (snd <$> kvs)
pure $ A.Object (HashMap.fromList (zip ks vs))
_ -> Nothing
where
isStr (String s) = pure s
isStr _ = Nothing
isStringy (String s) = pure s
isStringy (Keyword (Ident i)) = pure i
isStringy _ = Nothing

-- | The environment, which keeps all known bindings.
newtype Env s = Env { fromEnv :: Map Ident (Doc.Docd s) }
Expand Down
7 changes: 6 additions & 1 deletion src/Radicle/Internal/PrimFns.hs
Expand Up @@ -565,7 +565,12 @@ purePrimFns = fromList $ allDocs $
v -> throwErrorHere $ TypeError "seq" 0 TStructure v
)
, ( "to-json"
, "Returns a JSON formatted string representing the input value."
, "Returns a JSON formatted string representing the input value. Numbers are only\
\ converted if they have a finite decimal expansion. Strings and booleans are\
\ converted to their JSON counterparts. Keywords are converted to JSON strings\
\ (dropping the initial ':'). Lists and vectors are converted to JSON arrays.\
\ Dicts are converted to JSON objects as long as all the keys are either\
\ strings or keywords."
, oneArg "to-json" $ \v -> String . toS . Aeson.encode <$>
maybeJson v ?? toLangError (OtherError "Could not serialise value to JSON")
)
Expand Down
2 changes: 2 additions & 0 deletions test/spec/Radicle/Tests.hs
Expand Up @@ -476,7 +476,9 @@ test_eval =

, testCase "'to-json' works" $ do
runPureCode "(to-json (dict \"foo\" #t))" @?= Right (String "{\"foo\":true}")
runPureCode "(to-json {:foo #t \"bar\" #f})" @?= Right (String "{\"foo\":true,\"bar\":false}")
runPureCode "(to-json (dict \"key\" (list 1 \"value\")))" @?= Right (String "{\"key\":[1,\"value\"]}")
runPureCode "(to-json [3/2 #f])" @?= Right (String "[1.5,false]")
noStack (runPureCode "(to-json (dict 1 2))") @?= Left (OtherError "Could not serialise value to JSON")

, testCase "def-rec can define recursive functions" $ do
Expand Down

0 comments on commit ac6e647

Please sign in to comment.