Experiment mapping custom-types to JSON

Hello :sunny:

I wanted to show off a technique I’ve been experimenting with, mapping to/from JSON with custom-types.

Background

I have a SPA application that uses automatic message-replay as part of the development-setup. This in turn requires me to maintain a Json.Decode.Decoder Msg and Msg -> Json.Encode.Value functions.

Goal

The “problem” for me is having to maintain a mapping from/to JSON for a custom-type. Encoding allows you to do nice exhaustive type-checking, but decoders do not. I would like to have a more maintainable approach to mapping between Elm/JSON values.

Technique

the JSON encode-function is mapping customType -> Json.Encode.Value. Since this mapping has exhaustive pattern-matching, I could perhaps modify its definition to:

  1. Return both an encoding of the value, along with a decoder for it?
  2. using a loop-function, generate a list of all variants, map them to decoders, and join them with Decode.oneOf

Example

I’ve tried to make an Ellie, but couldn’t save it, so here’s a gist of the idea. The code is brittle, but should illustrate my approach, and could perhaps be a starting-point for a nice API?

Let me know if you have suggestions for improvements, simplifications, or whatever you think!

Happy hacking!

3 Likes

You may be interested by miniBill/elm-codec custom types codec.

4 Likes

I suppose Codec.custom is the kind of API I wanted to get to :smile: thanks for the link!

3 Likes

In the app that I’m currently building, I’m using elm-codec to send out json encoded types and then converting the json into algebraic data types in the Python (Flask) back end using this module https://pypi.org/project/algebraic-data-types/ combined with data classes to represent records. It’s working well so I’d recommend elm-codec for this kind of thing.

2 Likes

I decided against using the module, as I need the same boilerplate to derive multiple things beyond json encoding/decoding. Im now deriving to/fromstring, enumeration and json en/decoding from a single pattern-match, in an extensible way :sunny:

1 Like

When you reach that stage I would seriously consider some codegen. I’ve written but not “published” a thing that does reflection on c# types and then codegens Codecs. It’s a bit of work, but knowing that the compiler has your back for client/server communication is awesome

2 Likes

I can relate to this, as my backend is built with Hasura (integrated using elm-graphql), so the compiler is already checking all client/server interaction for me during CI. It’s really great!

I’ve experimented with codegen in the past, and it wasn’t a great experience:

  • How to deal with opaque-types exposed from 3rd-party-libraries. For example elm/file's File-value?
  • Maybe I want enumeration (msg -> List msg) too? toString/fromString?

My current approach gives me flexibility dealing with these issues without very much upfront work :sunny:

1 Like

I have also been working on code generators that can do things like turning a data model into Elm JSON codecs:

Its based on a data modelling language which looks very similar to Elms type system, but with no type variables (concrete types only), and no extensible records. The idea is that whatever source you are generating from first goes into a language neutral description of the data model, and then code is generated from that.

Currently using it to take AWS service descriptors and generate the Elm client stubs for them.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.