elm-open-api-cli icon indicating copy to clipboard operation
elm-open-api-cli copied to clipboard

Enum decoders don't validate decoded strings

Open adamdicarlo0 opened this issue 9 months ago • 0 comments

Describe the bug

Enum properties are created as strings, rather than custom types, and their decoders don't validate the decoded strings.

To Reproduce

Run the generator with this schema:

openapi: 3.0.1
info:
  title: "Enums"
  version: "1"
components:
  schemas:
    Widget:
      type: object
      properties:
        stringEnum:
          type: string
          enum: ["a", "b", "c"]
      required:
        - stringEnum

Current outputs

module Enums.Types exposing (Widget)


type alias Widget =
    { stringEnum : String }
module Enums.Json exposing
    ( encodeWidget
    , decodeWidget
    )

import Enums.Types
import Json.Decode
import Json.Encode
import OpenApi.Common


encodeWidget : Enums.Types.Widget -> Json.Encode.Value
encodeWidget rec =
    Json.Encode.object [ ( "stringEnum", Json.Encode.string rec.stringEnum ) ]


decodeWidget : Json.Decode.Decoder Enums.Types.Widget
decodeWidget =
    Json.Decode.succeed
        (\stringEnum -> { stringEnum = stringEnum })
        |> OpenApi.Common.jsonDecodeAndMap
            (Json.Decode.field "stringEnum" Json.Decode.string)

Ideal outputs

Ideally, the outputs would be something like this:

module Enums.Types exposing (Widget, StringEnum(..))


type StringEnum = StringEnum_A | StringEnum_B | StringEnum_C

type alias Widget =
    { stringEnum : StringEnum }
module Enums.Json exposing
    ( encodeWidget
    , decodeWidget
    )

import Enums.Types
import Json.Decode
import Json.Encode
import OpenApi.Common


encodeStringEnum : Enums.Types.StringEnum -> Json.Encode.Value
encodeStringEnum value =
    case value of
        Enums.Types.StringEnum_A ->
            Json.Encode.string "a"

        Enums.Types.StringEnum_B ->
            Json.Encode.string "b"

        Enums.Types.StringEnum_C ->
            Json.Encode.string "c"


decodeStringEnum : Json.Decode.Decoder Enums.Types.StringEnum
decodeStringEnum =
    Json.Decode.string
        |> Json.Decode.andThen
            (\value ->
                case value of
                    "a" ->
                        Json.Decode.succeed Enums.Types.StringEnum_A
              
                    "b" ->
                        Json.Decode.succeed Enums.Types.StringEnum_B
              
                    "c" ->
                        Json.Decode.succeed Enums.Types.StringEnum_C

                    _ ->
                        Json.Decode.fail ("Bad StringEnum value, " ++ value)
            )


encodeWidget : Enums.Types.Widget -> Json.Encode.Value
encodeWidget rec =
    Json.Encode.object [ ( "stringEnum", encodeStringEnum rec.stringEnum ) ]


decodeWidget : Json.Decode.Decoder Enums.Types.Widget
decodeWidget =
    Json.Decode.succeed
        (\stringEnum -> { stringEnum = stringEnum })
        |> OpenApi.Common.jsonDecodeAndMap
            (Json.Decode.field "stringEnum" decodeStringEnum)

adamdicarlo0 avatar May 01 '25 18:05 adamdicarlo0