Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Decoding ill-formated JSON in Elm, using RSS enclosure as an example
-- copy me to http://elm-lang.org/try
import Html exposing (text)
import Json.Decode as Json exposing ((:=))
import String
import Regex
type alias Model =
{ list : List Item }
type alias Item =
{ url : String }
main =
let
model = Json.decodeString decodeModel jsonString
in
case model of
Ok model_ ->
model_.list
|> List.map (\item -> item.url)
|> String.join ","
|> text
Err err ->
text <| "decode failed : " ++ err
jsonString = """
{ "items":
[ { "enclosure":{ "url":"AAA", "type":"audio/mpeg" } }
, { "enclosure":{ "url":"BBB", "type":"video/mp4" } }
, { "enclosure":
[ { "url":"CCC", "type":"video/mp4" }
, { }
, { "url":"DDD", "type":"audio/mpeg" }
]
}
, {}
]
}
"""
decodeSingleEnclosure : Json.Decoder (String, String)
decodeSingleEnclosure =
Json.object2 (,)
("url" := Json.string)
("type" := Json.string)
decodeSingleEnclosureUrl : Json.Decoder String
decodeSingleEnclosureUrl =
decodeSingleEnclosure
`Json.andThen`
(\(url, type_) ->
if Regex.contains (Regex.regex "^audio/") type_ then
Json.succeed url
else
Json.fail "not audio type"
)
decodeEnclosureListUrl : Json.Decoder String
decodeEnclosureListUrl =
Json.list (Json.maybe decodeSingleEnclosureUrl)
`Json.andThen`
(\list -> -- List (Maybe String)
let
head = list
|> List.filterMap identity
|> List.head
in
case head of
Just first ->
Json.succeed first
Nothing ->
Json.fail "cannot get enclosure"
)
decodeEnclosureUrl : Json.Decoder String
decodeEnclosureUrl =
Json.oneOf
[ "enclosure" := decodeSingleEnclosureUrl
, "enclosure" := decodeEnclosureListUrl
]
decodeItem: Json.Decoder (Maybe Item)
decodeItem =
Json.maybe (
Json.object1 Item
decodeEnclosureUrl
)
decodeModel : Json.Decoder Model
decodeModel =
Json.map Model
( ("items" := Json.list decodeItem)
`Json.andThen`
(\list -> list
|> List.filterMap identity
|> Json.succeed
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment