Search code examples
haskellserializationyamlaeson

Serialize a map to YAML with a specific order


I use the yaml library to serialize a value of type Map String t (or some type t). The order in the resulting output is rather random, which is suboptimal, as the file should be human readable.

Is there a way to control the serialization order of a map? Or, probably closer to the core of the problem, an aeson Object? If not, what are suitable workarounds?


Solution

  • Since 0.8.13, the yaml package contains the Data.Yaml.Prettty module. This allows you to configure how to pretty-print yaml documents, including ordering fields using setConfCompare

    In one of my own projects, I started using it with a change like this:

     writeTipToiYaml :: FilePath -> TipToiYAML -> IO ()
    -writeTipToiYaml out tty = encodeFile out tty
    +writeTipToiYaml out tty =
    +    SBC.writeFile out (encodePretty opts tty)
    +  where
    +    opts = setConfCompare (compare `on` fieldIndex) defConfig
    +    fieldIndex s = fromMaybe (length fields) $ s `elemIndex` fields
    +    fields = map T.pack
    +        [ "product-id"
    +        , "comment"
    +        , "welcome"
    +        , "media-path"
    +        , "gme-lang"
    +        , "init"
    +        , "scripts"
    +        , "language"
    +        , "speak"
    +        , "scriptcodes"
    +        ]