Last active
November 9, 2017 16:49
-
-
Save jamesmacaulay/eff482aa05379e9267dd1e85fbff5c6d to your computer and use it in GitHub Desktop.
Json.Bidirectional.Coder hoisting subset of object's fields into a tuple https://ellie-app.com/h5Sb2g8b4a1/0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main exposing (main) | |
import Html exposing (Html, text) | |
import Json.Bidirectional as Json | |
import Json.Decode as Decode | |
import Json.Encode as Encode | |
import String | |
import Tuple | |
type Currency | |
= Usd | |
| Jpy | |
type alias Item = | |
{ name : String | |
, price : ( Int, Currency ) | |
} | |
currencyEncoder : Currency -> Encode.Value | |
currencyEncoder x = | |
case x of | |
Usd -> | |
Encode.string "USD" | |
Jpy -> | |
Encode.string "JPY" | |
currencyDecoder : Decode.Decoder Currency | |
currencyDecoder = | |
Decode.string | |
|> Decode.andThen | |
(\x -> | |
case x of | |
"USD" -> | |
Decode.succeed Usd | |
"JPY" -> | |
Decode.succeed Jpy | |
_ -> | |
Decode.fail "invalid currency" | |
) | |
currency : Json.Coder Currency | |
currency = | |
Json.custom currencyEncoder currencyDecoder | |
itemConstructor : String -> Int -> Currency -> Item | |
itemConstructor name amount currency = | |
{ name = name, price = ( amount, currency ) } | |
item : Json.Coder Item | |
item = | |
Json.object itemConstructor | |
|> Json.withField "name" .name Json.string | |
|> Json.withField "amount" (.price >> Tuple.first) Json.int | |
|> Json.withField "currency" (.price >> Tuple.second) currency | |
root : Json.Coder Item | |
root = | |
item | |
|> Json.at [ "item" ] | |
jsonDocument : String | |
jsonDocument = | |
""" | |
{ | |
"item": { | |
"name": "Item A", | |
"amount": 10, | |
"currency": "USD" | |
} | |
} | |
""" | |
main : Html msg | |
main = | |
let | |
decoded = | |
Json.decodeString root jsonDocument | |
reEncoded = | |
Result.map (Json.encodeString root 0) decoded | |
roundTripEquivalence = | |
decoded == (reEncoded |> Result.andThen (Json.decodeString root)) | |
in | |
text <| | |
toString <| | |
{ decoded = decoded | |
, reEncoded = reEncoded | |
, roundTripEquivalence = roundTripEquivalence | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment