The following functions should be available in Elm's standard library:
module Json where
parse : String -> Maybe JsonValue
getProp : String -> JsonValue -> Maybe JsonValue
toString : JsonValue -> Maybe String
toInt : JsonValue -> Maybe Int
toFloat : JsonValue -> Maybe Float
toBool : JsonValue -> Maybe Bool
isNull : JsonValue -> Bool
arrayMap : (JsonValue -> Maybe a) -> JsonValue -> Maybe [a]
module Maybe where
getDefault : a -> Maybe a -> a
both : (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c
andThen : Maybe a -> (a -> Maybe b) -> Maybe b
Here is an example of manual JSON parsing in Elm 0.12 (author David Biro):
stringToResult = jsonToResult << stringToJson
stringToJson : String -> Json.Value
stringToJson str =
case Json.fromString str of
Just value -> value
Nothing -> Json.String ""
jsonToResult : Json.Value -> [SearchResultEntry]
jsonToResult value =
case value of
Json.Object dict ->
case Dict.get "items" dict of
Just (Json.Array items) -> justs (map itemJsonToEntry items)
Nothing -> []
otherwise -> []
itemJsonToEntry : Json.Value -> Maybe SearchResultEntry
itemJsonToEntry item =
case item of
Json.Object dict ->
case Dict.get "link" dict of
Just (Json.String url) ->
case Dict.get "image" dict of
Just imageJson -> Just (imageJsonToEntry url imageJson)
otherwise -> Nothing
otherwise -> Nothing
otherwise -> Nothing
imageJsonToEntry : String -> Json.Value -> SearchResultEntry
imageJsonToEntry url imageJson =
{ url = url
, width = getIntPropOrElse 0 "width" imageJson
, height = getIntPropOrElse 0 "height" imageJson
, thumbnailUrl = getStringPropOrElse "" "thumbnailLink" imageJson
, thumbnailWidth = getIntPropOrElse 0 "thumbnailWidth" imageJson
, thumbnailHeight = getIntPropOrElse 0 "thumbnailHeight" imageJson
}
With the proposed JSON API, the example can be simplified to:
stringToResult : String -> [SearchResultEntry]
stringToResult str =
Json.parse str
`Maybe.andThen` Json.getProp "items"
`Maybe.andThen` Json.arrayMap itemJsonToEntry
|> Maybe.getDefault []
itemJsonToEntry : Json.JsonValue -> Maybe SearchResultEntry
itemJsonToEntry item =
let url = Json.getProp "link" item |> Json.toString
image = Json.getProp "image" item
in
Maybe.both imageJsonToEntry url image
imageJsonToEntry url imageJson =
let getProp p = Json.getProp p imageJson
getIntOrZero p = getProp p |> Json.toInt |> Maybe.getDefault 0
in
{
url = url,
width = getIntOrZero "width",
height = getIntOrZero "height",
thumbnailUrl = getProp "thumbnailLink" |> Json.toString |> Maybe.getDefault "",
thumbnailWidth = getIntOrZero "thumbnailWidth",
thumbnailHeight = getIntOrZero "thumbnailHeight",
}