问题描述
说我有一个JSON文件,位于 http://www.randomurl.com/jobs.json ,看起来像这样:
Say I have a JSON file located at http://www.randomurl.com/jobs.json, it looks like this:
{ "jobs": [
{ "task" : "turn burgers" ,
"who" : "Anni" ,
"place" : "Quick"}
,
{ "task" : "dishes" ,
"who" : "Bob" ,
"place" : "McDo"}
]}
我制作了一个解码器:
type alias Job = {
task : String
, who : String
, place: String
}
type alias Jobs = List Job
decoder : Decoder Job
decoder =
Decode.object3 Job
(Decode.at ["attributes", "task"] Decode.string)
(Decode.at ["attributes", "who"] Decode.string)
(Decode.at ["attributes", "place"] Decode.string)
decoderColl : Decoder Jobs
decoderColl =
Decode.object1 identity
("jobs" := Decode.list decoder)
如何使用解码器从该网站读取文件?我想我需要Http包,但我不知道如何应用它.
How can I read in the file from that website using my decoder? I presume I need the Http package but I don't know how to apply it.
推荐答案
首先关闭-您的decoder
函数略有关闭.没有中间的属性"对象,因此您可以将其更改为:
First off - your decoder
function is slightly off. There is no intermediate "attributes" object, so you can change it to this:
decoder : Decoder Job
decoder =
Decode.object3 Job
("task" := Decode.string)
("who" := Decode.string)
("place" := Decode.string)
您正确地需要 elm-http 包.使用此功能,您可以创建Http.get
任务,将结果映射到操作.
You are correct that you'll need the elm-http package. Using this, you can create an Http.get
task which maps the result to an action.
作为一个基本示例,让我们创建一个按钮,以从URL下拉作业列表.我们需要一个GetJobs
动作来触发HTTP请求,以及一个ShowJobs
动作,当请求成功返回时将触发该动作.
As a basic example, let's make a button that pulls down the list of jobs from a url. We'll need a GetJobs
action to trigger the HTTP request, and a ShowJobs
action which will be trigged when the request returns successfully.
假设我们的操作类型如下:
Assuming our Action type looks like this:
type Action
= NoOp
| GetJobs
| ShowJobs (Maybe Jobs)
然后,我们可以创建一个getJobs
函数,该函数构建可以运行的任务.对于这个简单的示例,我们可以使用Task.toMaybe
来抑制任何HTTP或JSON解码错误.
Then we can create a getJobs
function that builds a task that can be run. For this simple example, we can use Task.toMaybe
to suppress any HTTP or JSON decoding errors.
getJobs : Effects Action
getJobs =
Http.get decoderColl jobsUrl
|> Task.toMaybe
|> Task.map ShowJobs
|> Effects.task
为了将它们粘合在一起,我们将使用 StartApp ,因为它可以让我们使用任务和效果.这是一个可以在本地构建的工作示例,假设Jobs.json位于同一目录中.
In order to glue it all together, we'll use StartApp since it lets us use tasks and effects. Here's a working example that you can build locally, assuming that jobs.json exists in the same directory.
import Http
import StartApp
import Effects exposing (Effects,Never)
import Task
import Html exposing (..)
import Html.Events exposing (..)
import Json.Decode as Decode exposing (Decoder, (:=))
jobsUrl = "./jobs.json"
-- StartApp plumbing
app =
StartApp.start { init = init, view = view, update = update, inputs = [] }
main =
app.html
port tasks : Signal (Task.Task Never ())
port tasks =
app.tasks
type Action
= NoOp
| GetJobs
| ShowJobs (Maybe Jobs)
type alias Model =
{ jobs : Maybe Jobs }
init =
({ jobs = Nothing }, Effects.none)
update action model =
case action of
NoOp ->
(model, Effects.none)
GetJobs ->
({ model | jobs = Nothing }, getJobs)
ShowJobs maybeJobs ->
({ model | jobs = maybeJobs }, Effects.none)
view address model =
div []
[ button [ onClick address GetJobs ] [ text "Click to get jobs!" ]
, viewJobs model.jobs
]
viewJobs maybeJobs =
let
viewJob job =
li [] [ text ("Task: " ++ job.task ++ "; Who: " ++ job.who ++ "; Place: " ++ job.place) ]
in
case maybeJobs of
Nothing ->
div [] [ text "No jobs to display. Try clicking the button" ]
Just jobs ->
ul [] (List.map viewJob jobs)
-- This is the key to map the result of the HTTP GET to an Action
-- Note: Task.toMaybe swallows any HTTP or JSON decoding errors
getJobs : Effects Action
getJobs =
Http.get decoderColl jobsUrl
|> Task.toMaybe
|> Task.map ShowJobs
|> Effects.task
-- An alternative to Task.toMaybe which dumps error information to the console log
toMaybeWithLogging : Task.Task x a -> Task.Task y (Maybe a)
toMaybeWithLogging task =
Task.map Just task `Task.onError` (\msg -> Debug.log (toString msg) (Task.succeed Nothing))
-- The Job type aliases from the question
type alias Job = {
task : String
, who : String
, place: String
}
type alias Jobs = List Job
-- The updated Job decoder
decoder : Decoder Job
decoder =
Decode.object3 Job
("task" := Decode.string)
("who" := Decode.string)
("place" := Decode.string)
decoderColl : Decoder Jobs
decoderColl =
Decode.object1 identity
("jobs" := Decode.list decoder)
这篇关于从JSON文件读入数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!