当前位置:  开发笔记 > 前端 > 正文

从JSON文件读入数据

如何解决《从JSON文件读入数据》经验,为你挑选了1个好方法。

假设我有一个位于http://www.randomurl.com/jobs.json的JSON文件,它看起来像这样:

{ "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包,但我不知道如何应用它.



1> Chad Gilbert..:

首先关闭 - 你的decoder功能略有偏差.没有中间的"属性"对象,因此您可以将其更改为:

decoder : Decoder Job
decoder =
  Decode.object3 Job
    ("task" := Decode.string)
    ("who" := Decode.string)
    ("place" := Decode.string)

你是正确的,你需要elm-http包.使用此功能,您可以创建Http.get将结果映射到操作的任务.

作为一个基本的例子,让我们创建一个按钮,从网址中下拉作业列表.我们需要一个GetJobs动作来触发HTTP请求,以及一个ShowJobs在请求成功返回时触发的动作.

假设我们的Action类型如下所示:

type Action
  = NoOp
  | GetJobs
  | ShowJobs (Maybe Jobs)

然后我们可以创建一个getJobs构建可以运行的任务的函数.对于这个简单的示例,我们可以使用Task.toMaybe来抑制任何HTTP或JSON解码错误.

getJobs : Effects Action
getJobs =
  Http.get decoderColl jobsUrl
    |> Task.toMaybe
    |> Task.map ShowJobs
    |> Effects.task

为了将它们粘合在一起,我们将使用StartApp,因为它允许我们使用任务和效果.这是一个可以在本地构建的工作示例,假设jobs.json存在于同一目录中.

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)

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有