本文介绍了从JSON文件读入数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个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文件读入数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 19:21