Elm:带有“type”属性的JSON类型别名

9

我有一些JSON数据,其中包含一个"type"属性,我想将其导入到Elm中。例如:{ "id": "abc", "type": "thing" } 然而,如果我定义一个包含type属性的类型别名,编译器会报错。例如:

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

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

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

严肃点?我必须重命名该属性吗?没有加引号或转义它的方法使它可以编译吗?
4个回答

8

是的,type 是一个保留关键字,在记录中不能用作字段名。

在 Elm 和 Haskell 中,你需要做的最常见的事情似乎是添加一个单引号,这样它就变成了 type',然后你的类型定义就变成了:

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

这起源于数学中的素数符号。一开始可能看起来有些奇怪,但它是有效的语法。

然后您可以使用以下Json解码器将JSON转换为Foo:

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

请注意,Elm 中的确切字段名称不需要与 JSON 字段名称匹配。

很少有语言可以让您使用关键字作为变量名,并不转义。此行为并不是 Elm 独有的。


追加单引号不会转义字段名,但是会将其更改为不同的名称。 - noah
我更新了我的回答,展示了JSON中的字段名称不需要与它解码后在Elm中的字段名称匹配。 - Chad Gilbert
在 Elm 0.16 中,在名称中使用单引号会出现严重错误。它会成为生成的 JS 中字符串字面量的开头。使用下划线代替单引号可以解决这个问题。 - Alex Korban
@AlexKorban - 我在 Elm 0.16 中没有遇到问题。定义 foo'bar' = "asdf" 完全没问题。 - Chad Gilbert
我在使用这个解决方案时遇到了“在变量名中遇到单引号。这在0.18版本中已被移除!”的错误。 - Dwayne Forde

3

现在您可以使用下划线来转义关键字。

例如:

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

2
在oscpad中,我在通过websockets的json接口中使用了一个“type”字段。但在elm记录中没有名为type的字段。我只是在解析JSON时查找“type”字段。我的代码如下:
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)

-1

无处可逃。Elm 不妥协。


有点粗暴的行为。如果有人正在使用一个他无法控制的API,那该怎么办呢? - marcosh
@marcosh 好的,你可以将关键字翻译成另一个字段/变量名,并且该名称仅在 Elm 中使用。如果通过端口导出到 JS,则必须将其编码回来。因此,字段名称不会完全匹配 JSON 属性名称,但这不是使用任何类型的 JSON 的障碍。只是我个人认为有点烦人。 - noah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接