dhall-json-1.7.5: Convert between Dhall and JSON or YAML
Safe HaskellNone
LanguageHaskell2010

Dhall.JSON

Description

This library only exports a single dhallToJSON function for translating a Dhall syntax tree to a JSON syntax tree (i.e. a Value) for the aeson library

NOTE: The yaml library uses the same Value type to represent YAML files, so you can use this to convert Dhall expressions to YAML, too

See the dhall package if you would like to transform Dhall source code into a Dhall syntax tree. Similarly, see the aeson package if you would like to translate a JSON syntax tree into JSON.

This package also provides dhall-to-json and dhall-to-yaml executables which you can use to compile Dhall source code directly to JSON or YAML for your convenience

Not all Dhall expressions can be converted to JSON since JSON is not a programming language. The only things you can convert are:

  • Bools
  • Naturals
  • Integers
  • Doubles
  • Text values
  • Lists
  • Optional values
  • unions
  • records

Dhall Bools translate to JSON bools:

$ dhall-to-json <<< 'True'
true
$ dhall-to-json <<< 'False'
false

Dhall numbers translate to JSON numbers:

$ dhall-to-json <<< '+2'
2
$ dhall-to-json <<< '2'
2
$ dhall-to-json <<< '2.3'
2.3

Dhall Text translates to JSON text:

$ dhall-to-json <<< '"ABC"'
"ABC"

Dhall Lists translate to JSON lists:

$ dhall-to-json <<< '[1, 2, 3] : List Natural'
[
  1,
  2,
  3
]

Dhall Optional values translate to null if absent and the unwrapped value otherwise:

$ dhall-to-json <<< 'None Natural'
null
$ dhall-to-json <<< 'Some 1'
1

Dhall records translate to JSON records:

$ dhall-to-json <<< '{ foo = 1, bar = True }'
{
  "bar": true,
  "foo": 1
}

Dhall unions translate to the wrapped value:

$ dhall-to-json <<< "< Left : Natural | Right : Natural>.Left 2"
2
$ cat config
let MyType =
      < Person : { age : Natural, name : Text } | Place : { location : Text } >

in  [ MyType.Person { age = 47, name = "John" }
    , MyType.Place { location = "North Pole" }
    , MyType.Place { location = "Sahara Desert" }
    , MyType.Person { age = 35, name = "Alice" }
    ]
$ dhall-to-json <<< "./config"
[
  {
    "age": 47,
    "name": "John"
  },
  {
    "location": "North Pole"
  },
  {
    "location": "Sahara Desert"
  },
  {
    "age": 35,
    "name": "Alice"
  }
]

You can preserve the name of the alternative if you wrap the value in a record with three fields:

  • contents: The union literal that you want to preserve the tag of
  • field: the name of the field that will store the name of the alternative
  • nesting: A value of type < Inline | Nested : Text >.

If nesting is set to Inline and the union literal stored in contents contains a record then the name of the alternative is stored inline within the same record. For example, this code:

let Example = < Left : { foo : Natural } | Right : { bar : Bool } >

let Nesting = < Inline | Nested : Text >

in  { field    = "name"
    , nesting  = Nesting.Inline
    , contents = Example.Left { foo = 2 }
    }

... produces this JSON:

{
  "foo": 2,
  "name": "Left"
}

If nesting is set to Nested nestedField then the union is stored underneath a field named nestedField. For example, this code:

let Example = < Left : { foo : Natural } | Right : { bar : Bool } >

let Nesting = < Inline | Nested : Text >

in  { field    = "name"
    , nesting  = Nesting.Nested "value"
    , contents = Example.Left { foo = 2 }
    }

... produces this JSON:

{
  "name": "Left",
  "value": {
    "foo": 2
  }
}

You can also translate Dhall expressions encoding weakly-typed JSON (see: https://prelude.dhall-lang.org/JSON/Type):

$ cat ./example.dhall
let JSON = https://prelude.dhall-lang.org/JSON/package.dhall

in  JSON.object
    [ { mapKey = "foo", mapValue = JSON.null }
    , { mapKey =
          "bar"
      , mapValue =
          JSON.array [ JSON.number 1.0, JSON.bool True ]
      }
    ]

By default, the fields that are evaluated to null will be removed, but here we're preserving them with the --preserveNull flag.

$ dhall-to-json --preserveNull <<< './example.dhall'
{
  "bar": [
    1,
    true
  ],
  "foo": null
}

Also, all Dhall expressions are normalized before translation to JSON:

$ dhall-to-json <<< "True == False"
false
Synopsis

Dhall to JSON

dhallToJSON :: Expr s Void -> Either CompileError Value Source #

Convert a Dhall expression to the equivalent JSON expression

>>> :set -XOverloadedStrings
>>> :set -XOverloadedLists
>>> import Core
>>> dhallToJSON (RecordLit [("foo", IntegerLit 1), ("bar", TextLit "ABC")])
Right (Object (fromList [("foo",Number 1.0),("bar",String "ABC")]))
>>> fmap Aeson.encode it
Right "{\"foo\":1,\"bar\":\"ABC\"}"

omitNull :: Value -> Value Source #

Omit record fields that are null

omitEmpty :: Value -> Value Source #

Omit record fields that are null, arrays and records whose transitive fields are all null

parsePreservationAndOmission :: Parser (Value -> Value) Source #

Combines parsers for command-line options related to preserving & omitting null fields.

data Conversion Source #

Specify whether or not to convert association lists of type List { mapKey: Text, mapValue : v } to records

Constructors

NoConversion 
Conversion 

Fields

convertToHomogeneousMaps :: Conversion -> Expr s Void -> Expr s Void Source #

Convert association lists to homogeneous maps

This converts an association list of the form:

[ { mapKey = k0, mapValue = v0 }, { mapKey = k1, mapValue = v1 } ]

... to a record of the form:

{ k0 = v0, k1 = v1 }

parseConversion :: Parser Conversion Source #

Parser for command-line options related to homogeneous map support

data SpecialDoubleMode Source #

This option specifies how to encode NaN/Infinity/-Infinity

Constructors

UseYAMLEncoding

YAML natively supports NaN/Infinity/-Infinity

ForbidWithinJSON

Forbid NaN/Infinity/-Infinity because JSON doesn't support them

ApproximateWithinJSON

Encode NaN/Infinity/-Infinity as null/1.7976931348623157e308/-1.7976931348623157e308, respectively

handleSpecialDoubles :: SpecialDoubleMode -> Expr s Void -> Either CompileError (Expr s Void) Source #

Pre-process an expression containing NaN/Infinity/-Infinity, handling them as specified according to the SpecialDoubleMode

codeToValue Source #

Arguments

:: Conversion 
-> SpecialDoubleMode 
-> Maybe FilePath

The source file path. If no path is given, imports are resolved relative to the current directory.

-> Text

Input text.

-> IO Value 

Convert a piece of Text carrying a Dhall inscription to an equivalent JSON Value

>>> :set -XOverloadedStrings
>>> import Core
>>> Dhall.JSON.codeToValue defaultConversion ForbidWithinJSON Nothing "{ a = 1 }"
>>> Object (fromList [("a",Number 1.0)])

Exceptions

data CompileError Source #

This is the exception type for errors that might arise when translating Dhall to JSON

Because the majority of Dhall language features do not translate to JSON this just returns the expression that failed