Parse and decode a Json File

Some Student data i get from a remote #Json File. now I want to #Decode that #JsonFile into #Elm in a way where i can count Total Number Of Student passed in every School, and a grand total of Student failed in all school. i appreciate your time. thank you so much [ NB: newbe]
{
“SchoolA”: [
{
“date”: “2020-1-1”,
“passed”: 2,
“failed”: 0,
},
{
“date”: “2020-1-2”,
“passed”: 3,
“failed”: 6,
},

],
“CollageB”: [
{
“date”: “2020-1-1”,
“passed”: 50,
“failed”: 20,
},
{
“date”: “2020-1-2”,
“passed”: 10,
“failed”: 30,
},

],
“UniversityC”: [
{
“date”: “2020-1-1”,
“passed”: 100,
“failed”: 50,
},
{
“date”: “2020-1-2”,
“passed”: 15,
“failed”: 25,
},

],


}

You can use something like this:
https://ellie-app.com/8BW2XKNg6hFa1

module Main exposing (main)

import Date exposing (Date)
import Dict exposing (Dict)
import Html exposing (Html)
import Json.Decode as Decode exposing (Decoder)


type alias School =
    List Exam


type alias Exam =
    { date : Date
    , passed : Int
    , failed : Int
    }


examDecoder : Decoder Exam
examDecoder =
    Decode.map3 Exam
        (Decode.field "date" dateDecoder)
        (Decode.field "passed" Decode.int)
        (Decode.field "failed" Decode.int)


schoolDecoder : Decoder School
schoolDecoder =
    Decode.list examDecoder


schoolsDecoder : Decoder (Dict String School)
schoolsDecoder =
    Decode.dict schoolDecoder


dateDecoder : Decoder Date
dateDecoder =
    Decode.string
        |> Decode.andThen toDateDecoder


toDateDecoder : String -> Decoder Date
toDateDecoder str =
    let
        isoString =
            str
                |> String.split "-"
                |> List.map (String.padLeft 2 '0')
                |> String.join "-"
    in
    case Date.fromIsoString isoString of
        Ok date ->
            Decode.succeed date

        Err error ->
            Decode.fail error


main : Html msg
main =
    case Decode.decodeString schoolsDecoder json of
        Ok schools ->
            Html.div []
                [ Html.text <| "Total passed: " ++ String.fromInt (sum .passed schools)
                , Html.br [] []
                , Html.text <| "Total failed: " ++ String.fromInt (sum .failed schools)
                ]

        Err error ->
            Html.text ("Error: " ++ Decode.errorToString error)


sum : (Exam -> Int) -> Dict String School -> Int
sum toValue schools =
    Dict.foldl
        (\_ exams total ->
            total + List.foldl (\exam schoolTotal -> schoolTotal + toValue exam) 0 exams
        )
        0
        schools

Thank you so much <3

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.