Ricerca…


Osservazioni

Json.Decode espone due funzioni per decodificare un payload, il primo è decodeValue che tenta di decodificare un Json.Encode.Value , il secondo è decodeString che tenta di decodificare una stringa JSON. Entrambe le funzioni richiedono 2 parametri, un decodificatore e una stringa Json.Encode.Value o Json.

Decodifica di un elenco

Il seguente esempio può essere testato su https://ellie-app.com/m9tk39VpQg/0 .

import Html exposing (..)
import Json.Decode 

payload =
  """
  ["fu", "bar"]
  """

main =
  Json.Decode.decodeString decoder payload -- Ok ["fu","bar"]
  |> toString
  |> text

decoder =
  Json.Decode.list Json.Decode.string

Pre-decodifica un campo e decodifica il resto in base a quel valore decodificato

I seguenti esempi possono essere testati su https://ellie-app.com/m9vmQ8NcMc/0 .

import Html exposing (..)
import Json.Decode

payload =
  """
  [ { "bark": true, "tag": "dog", "name": "Zap", "playful": true }
  , { "whiskers": true, "tag" : "cat", "name": "Felix" }
  , {"color": "red", "tag": "tomato"}
  ]
  """

-- OUR MODELS

type alias Dog =
  { bark: Bool
  , name: String
  , playful: Bool
  }
  
type alias Cat =
  { whiskers: Bool
  , name: String
  }

-- OUR DIFFERENT ANIMALS

type Animal 
  = DogAnimal Dog
  | CatAnimal Cat
  | NoAnimal

main =
  Json.Decode.decodeString decoder payload
  |> toString
  |> text

decoder =
  Json.Decode.field "tag" Json.Decode.string
    |> Json.Decode.andThen animalType
    |> Json.Decode.list 

animalType tag =
  case tag of
    "dog" ->
      Json.Decode.map3 Dog 
          (Json.Decode.field "bark" Json.Decode.bool) 
          (Json.Decode.field "name" Json.Decode.string) 
          (Json.Decode.field "playful" Json.Decode.bool) 
        |> Json.Decode.map DogAnimal
    "cat" ->
      Json.Decode.map2 Cat 
          (Json.Decode.field "whiskers" Json.Decode.bool) 
          (Json.Decode.field "name" Json.Decode.string)
        |> Json.Decode.map CatAnimal
    _ ->
      Json.Decode.succeed NoAnimal

Decodifica JSON da Rust enum

Questo è utile se si utilizza la ruggine nel back-end e l'elm sul front-end

enum Complex{
    Message(String),
    Size(u64)
}

let c1 = Complex::Message("hi");
let c2 = Complex::Size(1024u64);

Il Json codificato dalla ruggine sarà:

c1:
    {"variant": "Message",
     "fields": ["hi"]
    }
c2:
    {"variant": "Size",
     "fields": [1024]
    }

Il decoder in olmo

import Json.Decode as Decode exposing (Decoder)

type Complex = Message String
    | Size Int

-- decodes json to Complex type
complexDecoder: Decoder Value
complexDecoder = 
    ("variant" := Decode.string `Decode.andThen` variantDecoder)

variantDecoder: String -> Decoder Value
variantDecoder variant =
    case variant of
        "Message" ->
            Decode.map Message 
                ("fields" := Decode.tuple1 (\a -> a) Decode.string)
        "Size" ->
            Decode.map Size
                ("fields" := Decode.tuple1 (\a -> a) Decode.int)
        _ ->
            Debug.crash "This can't happen"

Utilizzo: i dati vengono richiesti da http rest api e la decodifica del payload sarà

    Http.fromJson complexDecoder payload

La decodifica da stringa sarà

    Decode.decodeString complexDecoder payload

Decodifica di un elenco di record

Il seguente codice può essere trovato in una demo qui: https://ellie-app.com/mbFwJT9jD3/0

import Html exposing (..)
import Json.Decode exposing (Decoder)

payload =
  """
  [{
      "id": 0,
      "name": "Adam Carter",
      "work": "Unilogic",
      "email": "[email protected]",
      "dob": "24/11/1978",
      "address": "83 Warner Street",
      "city": "Boston",
      "optedin": true
    },
    {
      "id": 1,
      "name": "Leanne Brier",
      "work": "Connic",
      "email": "[email protected]",
      "dob": "13/05/1987",
      "address": "9 Coleman Avenue",
      "city": "Toronto",
      "optedin": false
    }]
  """
  
type alias User =
  { name: String
  , work: String
  , email: String
  , dob: String
  , address: String
  , city: String
  , optedin: Bool
  }
 
main =
  Json.Decode.decodeString decoder payload
  |> toString
  |> text

decoder: Decoder (List User)
decoder =
    Json.Decode.map7 User 
    (Json.Decode.field "name" Json.Decode.string)
    (Json.Decode.field "work" Json.Decode.string)
    (Json.Decode.field "email" Json.Decode.string)
    (Json.Decode.field "dob" Json.Decode.string)
    (Json.Decode.field "address" Json.Decode.string)
    (Json.Decode.field "city" Json.Decode.string)
    (Json.Decode.field "optedin" Json.Decode.bool)
    |> Json.Decode.list 

Decodifica una data

Nel caso tu abbia JSON con una stringa data ISO come questa

JSON.stringify({date: new Date()})
// -> "{"date":"2016-12-12T13:24:34.470Z"}"

Puoi mapparlo a elm Date type:

import Html exposing (text)
import Json.Decode as JD
import Date

payload = """{"date":"2016-12-12T13:24:34.470Z"}"""

dateDecoder : JD.Decoder Date.Date
dateDecoder =
  JD.string
    |> JD.andThen ( \str ->
          case Date.fromString str of
            Err err -> JD.fail err
            Ok date -> JD.succeed date )

payloadDecoder : JD.Decoder Date.Date
payloadDecoder =
  JD.field "date" dateDecoder

main =
  JD.decodeString payloadDecoder payload
  |> toString
  |> text

Decodifica un elenco di oggetti contenenti elenchi di oggetti

Vedi Ellie per un esempio funzionante. Questo esempio utilizza il modulo NoRedInk / elm-decode-pipeline .

Dato un elenco di oggetti JSON, che contengono elenchi di oggetti JSON:

[
  {
    "id": 0,
    "name": "Item 1",
    "transactions": [
      { "id": 0, "amount": 75.00 },
      { "id": 1, "amount": 25.00 }
    ]
  },
  {
    "id": 1,
    "name": "Item 2",
    "transactions": [
      { "id": 0, "amount": 50.00 },
      { "id": 1, "amount": 15.00 }
    ]
  }
]

Se la stringa precedente si trova nella stringa del payload , può essere decodificata utilizzando quanto segue:

module Main exposing (main)

import Html exposing (..)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline as JP
import String


type alias Item =
    { id : Int
    , name : String
    , transactions : List Transaction
    }


type alias Transaction =
    { id : Int
    , amount : Float
    }


main =
    Decode.decodeString (Decode.list itemDecoder) payload
        |> toString
        |> String.append "JSON "
        |> text



itemDecoder : Decoder Item
itemDecoder =
    JP.decode Item
        |> JP.required "id" Decode.int
        |> JP.required "name" Decode.string
        |> JP.required "transactions" (Decode.list transactionDecoder)


transactionDecoder : Decoder Transaction
transactionDecoder =
    JP.decode Transaction
        |> JP.required "id" Decode.int
        |> JP.required "amount" Decode.float


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow