Serialize a map to YAML with a specific order

aeson, haskell, serialization, yaml

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"
+        ]

Problem

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?

Original source