Generate type safe json decoders and encoders from OAS

Hey!
I wanted to share a thing I created and get feedback on the idea as well. :slight_smile:

Problem in rough terms - as far as I can tell, traditionally generated Elm SDKs have used records for API inputs and outputs, but some languages run servers side often aren’t great about even acknowledging that non-nullable types exist. Nullability is kinda weird in OAS as well, so you might end up generating records where very field is a Maybe. This is especially bad when interacting with large legacy systems.
But if a spec exists, I still want to get guarantees at least about the stuff that’s in the spec.
Also something being “required” in the spec doesn’t mean it’s not null, just that the field is required.
For encoding I may want to omit required fields and rely on BE validation to tell me what to include.

Solution - generate the rough shape of a JSON schema as a type alias like:

type alias Profile =
    { obj :
        { username : Required { str : Sdk.Key.Supported }
        , bio : { str : Sdk.Key.Supported }
        , image : Required { str : Sdk.Key.Supported }
        , following : Required { bool : Sdk.Key.Supported }
        }
    }

And require that shape in the decoder and encoder types.

createArticle : Cmd Msg
createArticle =
  let
    input : Encode.Value Sdk.NewArticleRequest
    input =
      Encode.object [
        Encode.pair Sdk.article <| Encode.object
          [ Encode.pair Sdk.title <| Encode.string articleTitle
          , Encode.pair Sdk.description <| Encode.string articleDescription
          , Encode.pair Sdk.body <| Encode.string articleBody
          , Encode.pair Sdk.tagList <| Encode.list Encode.string articleTags
          ]
      ]

    decoder : Decode.Decoder Sdk.SingleArticleResponse Article
    decoder =
      Decode.field Sdk.article articleDecoder
  in
    Sdk.createArticle
      { body = Sdk.jsonBody input
      , expect = Sdk.expectJson ArticleCreateReceived decoder
      }

I have included the generated code in the repository as well for easier browsing.

1 Like