1

I am trying to rename keys when serializing an object to json.

I understand the way to do that is to, rather than just using deriving generic, define an instance with custom key names like so:

-- instance ToJSON R2  -- old
instance ToJSON R2 where
  toJSON (R2 recCode recDate) = object [ "code" .= recCode , "date" .= recDate ]
-- new

However, this gives me:

<interactive>:2:70: error:
    Ambiguous occurrence ‘.=’
    It could refer to either ‘Data.Aeson..=’, imported from ‘Data.Aeson’ (and originally defined in ‘aeson-1.3.1.1:Data.Aeson.Types.ToJSON’)
                          or ‘Control.Lens..=’, imported from ‘Control.Lens’ (and originally defined in ‘Control.Lens.Setter’)

My attempt to fix this was to explicitly force the meaning of the .= operator by defining it in my code, eg:

(.=) = Data.Aeson.(.=)

This was a guess, but seems like the wrong syntax. I added the parens by analogy to the following resources:

This gave me this error:

(.=) = Data.Aeson (.=)

<interactive>:1:8: error:
    Not in scope: data constructor ‘Data.Aeson’
    No module named ‘Data’ is imported.

What is the correct syntax to say, "let .= be unambiguously the .= from Data.Aeson" ?

Mittenchops
  • 18,633
  • 33
  • 128
  • 246

2 Answers2

7

If you're OK with defining .= in your file to be the one from Aeson, you can simply hide the import of .= from Control.Lens:

import Control.Lens hiding ((.=))

Outer brackets are the import hiding list, inner brackets required due to .= being an operator - that is, having a name with non-alphanumeric characters.

Koterpillar
  • 7,883
  • 2
  • 25
  • 41
2

The answer can be found by reading the error output more carefully to see two periods, and surrounding the (whole thing) with parens as an operator. This works

(.=) = (Data.Aeson..=)
Mittenchops
  • 18,633
  • 33
  • 128
  • 246
  • The trouble with this is that it just adds an additional ambiguity if defined at the top level. (If defined locally, it just shadows the top-level definitions, of course.) This notation can be used inline, though: either `"code" Data.Aeson..= recCode`, or `"code" A..= recCode` given `import qualified Data.Aeson as A`. Still, hiding the Lens import—or better, using an explicit import list and omitting `(.=)` from it—is preferable. – Jon Purdy Apr 18 '19 at 06:54