Skip to content

Commit

Permalink
a bit nicer(?) json decoding
Browse files Browse the repository at this point in the history
introduce "byField" helper, mostly
  • Loading branch information
robx authored and alicebob committed Feb 3, 2018
1 parent e1ccb7d commit b6c5820
Showing 1 changed file with 77 additions and 65 deletions.
142 changes: 77 additions & 65 deletions elm/Mpd.elm
Original file line number Diff line number Diff line change
Expand Up @@ -102,44 +102,59 @@ type WSMsg
| WSDatabase


wsMsgDecoder : Decode.Decoder WSMsg
wsMsgDecoder =
Decode.field "type" Decode.string
byField : String -> List ( String, Decode.Decoder a ) -> Decode.Decoder a
byField field decoders =
let
lookup key kvs =
case kvs of
( k, v ) :: rest ->
if k == key then
Just v
else
lookup key rest

[] ->
Nothing
in
Decode.field field Decode.string
|> Decode.andThen
(\t ->
case t of
"status" ->
Decode.field "msg" (Decode.map WSStatus statusDecoder)

"playlist" ->
Decode.field "msg" (Decode.map WSPlaylist playlistDecoder)

"inodes" ->
Decode.map2
WSInode
(Decode.field "id" Decode.string)
(Decode.field "msg" (Decode.list inodeDecoder))

"list" ->
Decode.map2
WSList
(Decode.field "id" Decode.string)
(Decode.field "msg" <| Decode.list dbentryDecoder)

"track" ->
Decode.map2
WSTrack
(Decode.field "id" Decode.string)
(Decode.field "msg" trackDecoder)

"database" ->
Decode.succeed WSDatabase

_ ->
Debug.crash "unknown type field"
case lookup t decoders of
Just d ->
d

Nothing ->
Decode.fail <| "type not found: " ++ t
)


wsMsgDecoder : Decode.Decoder WSMsg
wsMsgDecoder =
byField "type"
[ ( "status", Decode.field "msg" <| Decode.map WSStatus statusDecoder )
, ( "playlist", Decode.field "msg" <| Decode.map WSPlaylist playlistDecoder )
, ( "inodes"
, Decode.map2
WSInode
(Decode.field "id" Decode.string)
(Decode.field "msg" <| Decode.list inodeDecoder)
)
, ( "list"
, Decode.map2
WSList
(Decode.field "id" Decode.string)
(Decode.field "msg" <| Decode.list dbentryDecoder)
)
, ( "track"
, Decode.map2
WSTrack
(Decode.field "id" Decode.string)
(Decode.field "msg" trackDecoder)
)
, ( "database", Decode.succeed WSDatabase )
]


decodeFloatString : Decode.Decoder Float
decodeFloatString =
Decode.string
Expand Down Expand Up @@ -193,40 +208,37 @@ playlistDecoder =
inodeDecoder : Decode.Decoder Inode
inodeDecoder =
Decode.oneOf
[ Decode.map2
Dir
(Decode.at [ "dir", "id" ] Decode.string)
(Decode.at [ "dir", "title" ] Decode.string)
, Decode.map2
File
(Decode.at [ "file", "id" ] Decode.string)
(Decode.at [ "file", "title" ] Decode.string)
[ Decode.field "dir" <|
Decode.map2
Dir
(Decode.field "id" Decode.string)
(Decode.field "title" Decode.string)
, Decode.field "file" <|
Decode.map2
File
(Decode.field "id" Decode.string)
(Decode.field "title" Decode.string)
]


dbentryDecoder : Decode.Decoder DBEntry
dbentryDecoder =
Decode.field "type" Decode.string
|> Decode.andThen
(\t ->
case t of
"artist" ->
Decode.map DBArtist
(Decode.field "artist" Decode.string)

"album" ->
Decode.map2 DBAlbum
(Decode.field "artist" Decode.string)
(Decode.field "album" Decode.string)

"track" ->
Decode.map5 DBTrack
(Decode.field "artist" Decode.string)
(Decode.field "album" Decode.string)
(Decode.field "title" Decode.string)
(Decode.field "id" Decode.string)
(Decode.field "track" Decode.string)

_ ->
Debug.crash "unknown type field"
)
byField "type"
[ ( "artist"
, Decode.map DBArtist
(Decode.field "artist" Decode.string)
)
, ( "album"
, Decode.map2 DBAlbum
(Decode.field "artist" Decode.string)
(Decode.field "album" Decode.string)
)
, ( "track"
, Decode.map5 DBTrack
(Decode.field "artist" Decode.string)
(Decode.field "album" Decode.string)
(Decode.field "title" Decode.string)
(Decode.field "id" Decode.string)
(Decode.field "track" Decode.string)
)
]

0 comments on commit b6c5820

Please sign in to comment.