1

我正在使用 postgrest (后端)和 elm (前端)构建一个应用程序,现在我正忙于编写解码器。我不太明白如何解码为我的特定类型,而不是像 int 和 string 这样的基本类型解码器。

当我看一下是如何string实现的第 73 到 75 行)时,它只是一个调用,Elm.Kernel.Json.decodeString而它又位于 elm 的 js 基础中。

我的 JSON 看起来像这样:

{ "id" : 1
, "parent_id" : 1
, "body" : "text of my body"
}

或者

{ "id" : 1
, "parent_id" : 1
, "sub_parent_id" : 2
}

是否可以将类似的内容解码为单个记录类型(Step),其中包含具有多个构造函数的自定义类型以匹配两个不同的字段(sub_parent_idbody)我的解码器看起来像这样但不编译

import Api.Parent.Step.Types exposing ( Step, StepContent )
import Json.Decode exposing (..)
import Json.Decode.Pipeline exposing (..)

decoder : Decoder Step
decoder = 
    succeed Step
        |> required "id" int
        |> oneOf
            [ field "stepContent" stepBodyDecoder
            , field "stepContent" subStepDecoder
            ]

stepBodyDecoder : Decoder StepContent
stepBodyDecoder = 
    succeed StepContent
        |> required "body" string

subStepDecoder : Decoder StepContent
subStepDecoder =
    succeed StepContent
        |> required "sub_parent_id" decoder

我的任何类型:

module Api.Parent.Step.Types exposing ( Step, StepContent )

type StepContent 
    = StepBody String
    | SubStep Step

type alias Step =
    { id : Int
    , stepContent : StepContent
    }
4

2 回答 2

1

JSON解码管道期望succeed传递一个函数,而StepContent不是一个函数,而是一个类型。然而,变体构造函数是函数,如果您查看编译器错误,它会建议正确的修复(尽管这有点巧合,因为它只是基于相似的名称提出建议):

I cannot find a `StepContent` variant:

28|     succeed StepContent
                ^^^^^^^^^^^
These names seem close though:

    StepBody
    Step
    OneOf
    SubStep

StepBody并且SubStep是您应该使用的。stepBodyDecoder将仅适用于该更改,并且将使您至少更进一步使用subStepDecoder,但类型和解码器与 JSON 不匹配。sub_parent_id是一个数字,而不是一个对象,所以看起来SubStep应该用 aInt而不是 a Step。然后,您可以在后续步骤中构建单独的分层数据结构。

于 2019-12-25T01:48:20.277 回答
0

解决方案以类型编写(通常)

oneOf : List (Decoder a) -> Decoder a

所以我们必须提供一个列表Decoder StepContent,它们是解码器函数。

根据相关评论,要构建一个StepContent值,我们需要形成构造函数: aStepBody或 a SubStep

import Api.Parent.Step.Types exposing ( Step, StepContent )
import Json.Decode exposing (..)
import Json.Decode.Pipeline exposing (..)

decoder : Decoder Step
decoder = 
    succeed Step
        |> required "id" int
        |> required "stepContent"  (oneOf [ stepBodyDecoder, subStepDecoder ] )


stepBodyDecoder : Decoder StepContent
stepBodyDecoder = 
    succeed StepBody
        |> required "body" string

subStepDecoder : Decoder StepContent
subStepDecoder =
    succeed SubStep
        |> required "sub_parent_id" decoder
于 2021-03-31T08:18:07.143 回答