Elm:解析JSON中的状态代码(带有潜在错误消息)

Elm:解析JSON中的状态代码(带有潜在错误消息),json,elm,Json,Elm,我一直很难用Elm解析JSON。我似乎已经掌握了基本知识,但由于某种原因,这一小块JSON让我感到困惑 下面是一个场景:我正在发布一个JSON API,该API将以以下两种格式之一返回: 如果请求成功: 如果失败: 我试图将此JSON响应编码为以下数据类型: type RequestStatus = Success | Error String type alias CreatePostResponse = { status : RequestStatus , post :

我一直很难用Elm解析JSON。我似乎已经掌握了基本知识,但由于某种原因,这一小块JSON让我感到困惑

下面是一个场景:我正在发布一个JSON API,该API将以以下两种格式之一返回:

如果请求成功:

如果失败:

我试图将此JSON响应编码为以下数据类型:

type RequestStatus = Success | Error String


type alias CreatePostResponse =
    { status : RequestStatus
    , post : Maybe Post }
到目前为止,我运气不好。我一直在阅读教程和指南,但似乎都没有把我带到正确的地方。以下是我目前掌握的代码:

createPostResponse : Decoder CreatePostResponse
createPostResponse =
    succeed CreatePostResponse
    |: (("status" := string) `andThen` (("error" := string) `andThen` decodeStatus))
    |: maybe ("post" := post)


decodeStatus : String -> String -> Decoder RequestStatus
decodeStatus status errorMessage = 
    succeed (case status of
        "success" -> Success
        "error" -> Error errorMessage
        _ -> Error "unknown")
显然,这会产生各种类型的错误,并且无法编译,但是我还没有找到一种好的方法将字符串从“message”字段获取到
RequestStatus
类型中


有人有什么想法吗?

这里有一个小的工作代码,它可以完成您想要的工作。为了具体起见,我冒昧地为
Post
类型假设了一个基本形状

import Json.Decode exposing (..)

type alias Post = { title: String, body: String }

type RequestStatus = Success Post | Error String

post: Decoder Post
post = object2 Post ("title" := string) ("body" := string)

requestStatusData: String -> Decoder RequestStatus
requestStatusData status =
    case status of
    "success" -> object1 Success ("post" := post)
    "error" -> object1 Error ("message" := string)
    _ -> fail <| status ++ " is not a valid value for request status"

decodeStatus : Decoder RequestStatus
decodeStatus =
    ("status" := string) `andThen` requestStatusData
  • 然后
    对一条记录进行解码,然后将该记录传递给一个函数,该函数执行其余的解码,因此
    requestStatusData
    需要如下所示:

    requestStatusData: String -> Decoder RequestStatus
    
    requestStatusData
    是一个
    成功帖子
    错误字符串
    。因此,我们需要两个分支,分别与状态
    “success”
    “error”
    关联(加上一个默认值以捕获格式错误的状态):

    首先使用定义为
    post
    的解码器解码
    “post”
    属性,然后对结果调用
    object1
    Success
    )的第一个参数。同样地

    object2 Post ("title" := string) ("body" := string)
    
    使用
    字符串
    解码器解码
    “title”
    ,然后使用
    字符串
    解码器解码
    “body”
    ,然后使用两个解码字符串作为参数调用
    Post
    函数。因此,我们最终得出以下结论:

    requestStatusData status =
        case status of
        "success" -> object1 Success ("post" := post)
        "error" -> object1 Error ("message" := string)
        _ -> fail <| status ++ " is not a valid value for request status"
    

    而不是
    RequestStatus
    而不丢失任何功能(您需要稍微更改
    requestStatusData
    ,但我将留给读者作为练习…)

    是的!这对我来说非常有效。非常感谢您花时间写下这篇文章(希望未来很多困惑的Elmer都会受到这篇文章的指导)。作为记录,我最终将我的
    RequestStatus
    类型更改为alias
    Result String Post
    ——这是一个很好的建议!很乐意帮忙。这也是巩固我对Elm的理解的一个好方法。一旦掌握了这些概念,将JSON反序列化为复杂类型将是一种很好的方式。
    requestStatusData: String -> Decoder RequestStatus
    
    requestStatusData status =
        case status of
        "success" -> makeSuccessWithPost
        "error" -> makeErrorWithString
        _ -> fail <| status ++ " is not a valid value for request status"
    
    object1 Success ("post" := post)
    
    object2 Post ("title" := string) ("body" := string)
    
    requestStatusData status =
        case status of
        "success" -> object1 Success ("post" := post)
        "error" -> object1 Error ("message" := string)
        _ -> fail <| status ++ " is not a valid value for request status"
    
    Result String Post