Simon H
Simon H

Reputation: 21037

Elm: Decode Json to a simple record structure

Struggling to find the right way to complete my Decoder. I start with data of the form

[{_id:'interests', [{obj1}, {obj1}]}
,{_id:'countries', [{obj2}, {...}]} 
,{_id:'sections', [{obj3}, {...}]}]

I want to get to a Decoder Summary where

type alias Summary =
    { sections : List Section
    , interests : List Interest
    , countries : List Country
    }

So far, the best I've been able to get to is an output of this sort:

[ Interests (List Interest), Countries (List Country), Sections (List Section)]

but that still requires some rather brittle pattern matching (relying upon a consistent order of the array and is therefore very problematic with 0.16). For that I use

summaryItemDecoder : String -> Decoder SummaryInfo
summaryItemDecoder item =
    let dec =
        case item of
            "sections" -> Json.map Sections sectionsDecoder
            "interests" -> Json.map Interests interestsDecoder
            "countries" -> Json.map Countries countriesDecoder
    in ("data" := dec)

listSummaryDecoder : Decoder (List SummaryInfo)
listSummaryDecoder =
    ("_id" := string) `Json.andThen` summaryItemDecoder
    |> list

Full code here. Grateful for some final tips

Upvotes: 3

Views: 596

Answers (2)

pdamoc
pdamoc

Reputation: 2923

You can fold the list of information into a Summary.

type Interest = Interest
type Section = Section
type Country = Contry

type Info =  Interests (List Interest) | Countries (List Country) | Sections (List Section) 


type alias Summary =
    { sections : List Section
    , interests : List Interest
    , countries : List Country
    }

emptySummary : Summary
emptySummary = 
    { sections = []
    , interests = []
    , countries = []
    }


toSummary : List Info -> Summary
toSummary xs = 
  let 
    insert info sum =
      case info of 
        Sections ss -> { sum | sections = ss }
        Interests is -> { sum | interests = is }
        Countries cs -> { sum | countries = cs } 

  in
    List.foldl insert emptySummary xs

infoList : List Info
infoList = []

summary = toSummary infoList 

Upvotes: 0

grumpyjames
grumpyjames

Reputation: 366

I'm not sure you can do much better; you are attempting to parse a format that can express things you cannot represent in your types, so your only option is to fail.

To satisfy the pattern matching gods, perhaps drop an otherwise clause in featuring the fail decoder? (http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Json-Decode#fail)

Upvotes: 2

Related Questions