Skip to content

Instantly share code, notes, and snippets.

@kspeakman
Last active August 4, 2018 13:50
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kspeakman/3f9521b0921b352c7d656261ec0a8fa6 to your computer and use it in GitHub Desktop.
Save kspeakman/3f9521b0921b352c7d656261ec0a8fa6 to your computer and use it in GitHub Desktop.
JsonStuff - Elm native module to auto-encode/decode JSON
port module Api exposing (..)
import JsonStuff exposing (ToJson, FromJson, getEncoder, getDecoder)
import Http
helpPostJson : String -> ToJson a msg -> FromJson b msg -> a -> Http.Request b
helpPostJson url toJson fromJson o =
Http.request
{ method = "POST"
, headers = []
, url = url
, body = getEncoder toJson o |> Http.stringBody "application/json"
, expect = getDecoder fromJson |> Http.expectJson
, timeout = Nothing
, withCredentials = False
}
-- stating the obvious: types and msgs here for example only
-- they should probably not be in this file
type alias SomeType =
{ anInt : Int
, aString : String
}
type Msg
= SomeTypeEchoed (Result Http.Error SomeType)
-- must declare ports so that the compiler generates encoders/decoders
-- outgoing generates encoder, incoming generates decoder
port someTypeOut : SomeType -> Cmd msg
port someTypeIn : (SomeType -> msg) -> Sub msg
echoSomeType : SomeType -> Cmd Msg
echoSomeType x =
helpPostJson "http://localhost/echo" someTypeOut someTypeIn x
|> Http.send SomeTypeEchoed
{
"version": "0.0.1",
"summary": "Example project",
"repository": "https://github.com/local/local.git",
"license": "MIT",
"source-directories": [
"src/Elm"
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "5.0.0 <= v < 6.0.0",
"elm-lang/html": "2.0.0 <= v < 3.0.0",
"elm-lang/http": "1.0.0 <= v < 2.0.0",
"elm-lang/navigation": "2.0.0 <= v < 3.0.0",
"evancz/elm-markdown": "3.0.1 <= v < 4.0.0",
},
"native-modules": true,
"elm-version": "0.18.0 <= v < 0.19.0"
}
module JsonStuff exposing (..)
import Native.JsonStuff
import Json.Decode exposing (Decoder)
type alias ToJson a msg =
a -> Cmd msg
type alias FromJson a msg =
(a -> msg) -> Sub msg
type alias Encode a =
a -> String
getEncoder : ToJson a msg -> Encode a
getEncoder outPort =
Native.JsonStuff.getEncoder outPort
getDecoder : FromJson a msg -> Decoder a
getDecoder inPort =
Native.JsonStuff.getDecoder inPort
// located at Native/JsonStuff.js
// must add "native-modules": true to elm-package.json
// first line must be changed to match author/project, format:
// var _[author]$[project]$Native_JsonStuff = function() {
var _local$local$Native_JsonStuff = function() {
var getEncoder = function(portFn) {
var portName = portFn(null).home;
var toJsObject = _elm_lang$core$Native_Platform.effectManagers[portName].converter;
var encoder = function(elmObject) {
return JSON.stringify(toJsObject(elmObject));
}
return encoder;
};
var getDecoder = function(portFn) {
var portName = portFn(null).home;
var decoder = _elm_lang$core$Native_Platform.effectManagers[portName].converter;
return decoder;
};
return {
getEncoder : getEncoder,
getDecoder : getDecoder
};}
();
@kspeakman
Copy link
Author

kspeakman commented Mar 17, 2017

Thanks to @mpdairy for this repo which showed me how to do the native bits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment