noah
noah

Reputation: 21519

Elm: Type alias for JSON with "type" property

I have some JSON with a "type" property that I want to import into Elm. e.g., { "id": "abc", "type": "thing" } However if I define a type alias with type as a property, the compiler complains. e.g.,

type alias Foo = {
      id: String
    , type: String
}

produces

It looks like the keyword `type` is being used as a variable.

3│     , type: String
              ^
Rename it to something else.

Seriously? I have to rename the property? Is there no way to quote or escape it so it will compile?

Upvotes: 9

Views: 1088

Answers (4)

Dwayne Forde
Dwayne Forde

Reputation: 1394

You can now escape the keyword with an underscore.

ex.

type alias Foo =
  { id: String
  , type_: String
}

Upvotes: 3

Chad Gilbert
Chad Gilbert

Reputation: 36385

Yes, type is a reserved keyword and cannot be used as a field name in a record.

In Elm and Haskell, the most common thing to do in your case seems to be to append a single quote, so it becomes type', and your type definition becomes

type alias Foo =
  { id: String
  , type': String
  }

This has its origin in the prime symbol from mathematics. It may look odd at first but it is valid syntax.

You can then use the following Json Decoder to translate the JSON into Foo:

fooDecoder =
  Json.object2
    Foo
    ("id" := Json.string)
    ("type" := Json.string)

Notice that the exact field name in Elm does not need to match the JSON field name.

Rarely will you find a language that lets you use keywords as variable names unescaped. This behavior is not unique to Elm.

Upvotes: 8

Bzzt
Bzzt

Reputation: 1054

In oscpad, I'm using a "type" field in my json interface over websockets. But I don't have a field called type in an elm record. I just look for a "type" field when I'm parsing JSON. My code looks like this:

jsSpec : JD.Decoder Spec
jsSpec =
  ("type" := JD.string) `JD.andThen` jsCs

jsCs : String -> JD.Decoder Spec
jsCs t =
  case t of
    "button" -> SvgButton.jsSpec `JD.andThen` (\a -> JD.succeed (CsButton a))
    "slider" -> SvgSlider.jsSpec `JD.andThen` (\a -> JD.succeed (CsSlider a))
    "label" -> SvgLabel.jsSpec `JD.andThen` (\a -> JD.succeed (CsLabel a))
    "sizer" -> jsSzSpec `JD.andThen` (\a -> JD.succeed (CsSizer a))
    _ -> JD.fail ("unkown type: " ++ t)

Upvotes: 2

noah
noah

Reputation: 21519

There is no escape. Elm is uncompromising.

Upvotes: -1

Related Questions