| Safe Haskell | None |
|---|---|
| Language | Haskell98 |
Dhall.JSONToDhall
Contents
Description
Convert JSON data to Dhall given a Dhall type expression necessary to make the translation unambiguous.
Reasonable requirements for conversion are:
- The Dhall type expression
tpassed as an argument tojson-to-dhallshould be a valid type of the resulting Dhall expression - A JSON data produced by the corresponding
dhall-to-jsonfrom the Dhall expression of typetshould (under reasonable assumptions) reproduce the original Dhall expression usingjson-to-dhallwith type argumentt
Only a subset of Dhall types consisting of all the primitive types as well as Optional, Union and Record constructs, is used for reading JSON data:
BoolsNaturalsIntegersDoublesTextsListsOptionalvalues- unions
- records
This library can be used to implement an executable which takes any data
serialisation format which can be parsed as an Aeson Value and converts
the result to a Dhall value. One such executable is json-to-dhall which
is used in the examples below.
Primitive types
JSON Bools translate to Dhall bools:
$ json-to-dhall Bool <<< 'true' True $ json-to-dhall Bool <<< 'false' False
JSON numbers translate to Dhall numbers:
$ json-to-dhall Integer <<< 2 +2 $ json-to-dhall Natural <<< 2 2 $ json-to-dhall Double <<< -2.345 -2.345
Dhall Text corresponds to JSON text:
$ json-to-dhall Text <<< '"foo bar"' "foo bar"
Lists and records
Dhall Lists correspond to JSON lists:
$ json-to-dhall 'List Integer' <<< '[1, 2, 3]' [ +1, +2, +3 ]
Dhall records correspond to JSON records:
$ json-to-dhall '{foo : List Integer}' <<< '{"foo": [1, 2, 3]}'
{ foo = [ +1, +2, +3 ] }Note, that by default, only the fields required by the Dhall type argument are parsed (as you commonly will not need all the data), the remaining ones being ignored:
$ json-to-dhall '{foo : List Integer}' <<< '{"foo": [1, 2, 3], "bar" : "asdf"}'
{ foo = [ +1, +2, +3 ] }If you do need to make sure that Dhall fully reflects JSON record data comprehensively, --records-strict flag should be used:
$ json-to-dhall --records-strict '{foo : List Integer}' <<< '{"foo": [1, 2, 3], "bar" : "asdf"}'
Error: Key(s) @bar@ present in the JSON object but not in the corresponding Dhall record. This is not allowed in presence of --records-strict:By default, JSON key-value arrays will be converted to Dhall records:
$ json-to-dhall '{ a : Integer, b : Text }' <<< '[{"key":"a", "value":1}, {"key":"b", "value":"asdf"}]'
{ a = +1, b = "asdf" }Attempting to do the same with --no-keyval-arrays on will result in error:
$ json-to-dhall --no-keyval-arrays '{ a : Integer, b : Text }' <<< '[{"key":"a", "value":1}, {"key":"b", "value":"asdf"}]'
Error: JSON (key-value) arrays cannot be converted to Dhall records under --no-keyval-arrays flag:Conversion of the homogeneous JSON maps to the corresponding Dhall association lists by default:
$ json-to-dhall 'List { mapKey : Text, mapValue : Text }' <<< '{"foo": "bar"}'
[ { mapKey = "foo", mapValue = "bar" } ]Flag --no-keyval-maps switches off this mechanism (if one would ever need it):
$ json-to-dhall --no-keyval-maps 'List { mapKey : Text, mapValue : Text }' <<< '{"foo": "bar"}'
Error: Homogeneous JSON map objects cannot be converted to Dhall association lists under --no-keyval-arrays flagOptional values and unions
Dhall Optional Dhall type allows null or missing JSON values:
$ json-to-dhall "Optional Integer" <<< '1' Some +1
$ json-to-dhall "Optional Integer" <<< null None Integer
$ json-to-dhall '{ a : Integer, b : Optional Text }' <<< '{ "a": 1 }'{ a = +1, b = None Text }
For Dhall union types the correct value will be based on matching the type of JSON expression:
$ json-to-dhall 'List < Left : Text | Right : Integer >' <<< '[1, "bar"]' [ < Left : Text | Right : Integer >.Right +1
, : Text | Right : Integer.Left "bar" ]
$ json-to-dhall '{foo : < Left : Text | Right : Integer >}' <<< '{ "foo": "bar" }'
{ foo = < Left : Text | Right : Integer >.Left "bar" }In presence of multiple potential matches, the first will be selected by default:
$ json-to-dhall '{foo : < Left : Text | Middle : Text | Right : Integer >}' <<< '{ "foo": "bar"}'
{ foo = < Left : Text | Middle : Text | Right : Integer >.Left "bar" }This will result in error if --unions-strict flag is used, with the list of alternative matches being reported (as a Dhall list)
$ json-to-dhall --unions-strict '{foo : < Left : Text | Middle : Text | Right : Integer >}' <<< '{ "foo": "bar"}'
Error: More than one union component type matches JSON value
...
Possible matches:: Text | Middle : Text | Right : Integer.Left "bar" > -------- : Text | Middle : Text | Right : Integer.Middle "bar"
Synopsis
- parseConversion :: Parser Conversion
- data Conversion = Conversion {
- strictRecs :: Bool
- noKeyValArr :: Bool
- noKeyValMap :: Bool
- unions :: UnionConv
- defaultConversion :: Conversion
- resolveSchemaExpr :: Text -> IO ExprX
- typeCheckSchemaExpr :: (Exception e, MonadCatch m) => (CompileError -> e) -> ExprX -> m ExprX
- dhallFromJSON :: Conversion -> ExprX -> Value -> Either CompileError ExprX
- data CompileError
- = TypeError (TypeError Src X)
- | BadDhallType ExprX ExprX
- | Mismatch ExprX Value
- | MissingKey Text ExprX Value
- | UnhandledKeys [Text] ExprX Value
- | NoKeyValArray ExprX Value
- | NoKeyValMap ExprX Value
- | ContainsUnion ExprX
- | UndecidableUnion ExprX Value [ExprX]
- showCompileError :: String -> (Value -> String) -> CompileError -> String
JSON to Dhall
parseConversion :: Parser Conversion Source #
Standard parser for options related to the conversion method
data Conversion Source #
JSON-to-dhall translation options
Constructors
| Conversion | |
Fields
| |
Instances
| Show Conversion Source # | |
Defined in Dhall.JSONToDhall Methods showsPrec :: Int -> Conversion -> ShowS # show :: Conversion -> String # showList :: [Conversion] -> ShowS # | |
defaultConversion :: Conversion Source #
Default conversion options
Parse schema code to a valid Dhall expression and check that its type is actually Type
typeCheckSchemaExpr :: (Exception e, MonadCatch m) => (CompileError -> e) -> ExprX -> m ExprX Source #
Check that the Dhall type expression actually has type Type
>>> :set -XOverloadedStrings
>>> import Dhall.Core
>>>typeCheckSchemaExpr id =<< resolveSchemaExpr "List Natural"App List Natural
>>>typeCheckSchemaExpr id =<< resolveSchemaExpr "+1"*** Exception: Error: Schema expression is succesfully parsed but has Dhall type: Integer Expected Dhall type: Type Parsed expression: +1
dhallFromJSON :: Conversion -> ExprX -> Value -> Either CompileError ExprX Source #
The main conversion function. Traversingzipping Dhall type and Aeson value trees together to produce a Dhall term/ tree, given Conversion options:
>>>:set -XOverloadedStrings>>>import qualified Dhall.Core as D>>>import qualified Dhall.Map as Map>>>import qualified Data.Aeson as A>>>import qualified Data.HashMap.Strict as HM
>>>s = D.Record (Map.fromList [("foo", D.Integer)])>>>v = A.Object (HM.fromList [("foo", A.Number 1)])>>>dhallFromJSON defaultConversion s vRight (RecordLit (fromList [("foo",IntegerLit 1)]))
Exceptions
data CompileError Source #
Constructors
| TypeError (TypeError Src X) | |
| BadDhallType ExprX ExprX | |
| Mismatch ExprX Value | |
| MissingKey Text ExprX Value | |
| UnhandledKeys [Text] ExprX Value | |
| NoKeyValArray ExprX Value | |
| NoKeyValMap ExprX Value | |
| ContainsUnion ExprX | |
| UndecidableUnion ExprX Value [ExprX] |
Instances
| Show CompileError Source # | |
Defined in Dhall.JSONToDhall Methods showsPrec :: Int -> CompileError -> ShowS # show :: CompileError -> String # showList :: [CompileError] -> ShowS # | |
| Exception CompileError Source # | |
Defined in Dhall.JSONToDhall Methods toException :: CompileError -> SomeException # fromException :: SomeException -> Maybe CompileError # displayException :: CompileError -> String # | |
showCompileError :: String -> (Value -> String) -> CompileError -> String Source #