Giter Club home page Giter Club logo

elm-json-decode-pipeline's Introduction

json-decode-pipeline

Build JSON decoders using the pipeline (|>) operator.

Motivation

It's common to decode into a record that has a type alias. Here's an example of this from the map3 docs:

type alias Job = { name : String, id : Int, completed : Bool }

point : Decoder Job
point =
  map3 Job
    (field "name" string)
    (field "id" int)
    (field "completed" bool)

This works because a record type alias can be called as a normal function. In that case it accepts one argument for each field (in whatever order the fields are declared in the type alias) and then returns an appropriate record built with those arguments.

The mapN decoders are straightforward, but require manually changing N whenever the field count changes. This library provides functions designed to be used with the |> operator, with the goal of having decoders that are both easy to read and easy to modify.

Examples

Here is a decoder built with this library.

import Json.Decode as Decode exposing (Decoder, decodeString, float, int, nullable, string)
import Json.Decode.Pipeline exposing (required, optional, hardcoded)


type alias User =
  { id : Int
  , email : Maybe String
  , name : String
  , percentExcited : Float
  }


userDecoder : Decoder User
userDecoder =
  Decode.succeed User
    |> required "id" int
    |> required "email" (nullable string) -- `null` decodes to `Nothing`
    |> optional "name" string "(fallback if name is `null` or not present)"
    |> hardcoded 1.0

In this example:

  • required "id" int is similar to (field "id" int)
  • optional is like required, but if the field is either null or not present, decoding does not fail; instead it succeeds with the provided fallback value.
  • hardcoded does not look at the provided JSON, and instead always decodes to the same value.

You could use this decoder as follows:

decodeString
  userDecoder
  """
    {"id": 123, "email": "[email protected]", "name": "Sam Sample"}
  """

The result would be:

{ id = 123
, email = Just "[email protected]"
, name = "Sam Sample"
, percentExcited = 1.0
}

Alternatively, you could use it like so:

decodeString
  userDecoder
  """
    {"id": 123, "email": null, "percentExcited": "(hardcoded)"}
  """

In this case, the result would be:

{ id = 123
, email = Nothing
, name = "(fallback if name is `null` or not present)"
, percentExcited = 1.0
}

NoRedInk

elm-json-decode-pipeline's People

Contributors

avh4 avatar eeue56 avatar ejames avatar freakingawesome avatar hecrj avatar jamesmacaulay avatar micahhahn avatar michaelglass avatar petemcfarlane avatar rofrol avatar rtfeldman avatar stoeffel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

elm-json-decode-pipeline's Issues

Porting to bucklescript-tea

Hi,
I think this library has a good approach to get around the limitations of the mapN functions in the regular Json.Decoder module. Would it be permitted under the current licensing to port the whole module or parts of the module to OCaml and include in the bucklescript-tea project?

Corrupt binary when compiling inside Docker

Hello, I'm working on a project where I compile the Elm sources inside a Docker container. We're using docker-compose to launch the development container and we access the Elm sources via a volume mapping the host directory where the sources live to a directory inside the container.

Whenever we compile the project we receive this message from elm-json-decode-pipeline:

Success! Compiled 8 modules.
-- CORRUPT BINARY - /home/project/.elm/0.19.0/package/NoRedInk/elm-json-decode-pipeline/1.0.0/objs.dat

The binary data at
/home/project/.elm/0.19.0/package/NoRedInk/elm-json-decode-pipeline/1.0.0/objs.dat
is corrupt.

Elm caches build artifacts in the following directories:

    /home/project/.elm
    elm-stuff/

Maybe you recently installed a command line tool or editor plugin that messes
with them? They definitely should not be doing that, but you never know! So
maybe try deleting them? Everything will be rebuilt from scratch. This may help
reveal the corrupting influence.

I've got no idea why this is happening. I'll leave the overall setup below:

  • Host OS: Mac OS Mojave 10.14.3
  • Docker for Mac 2.0.2.1
  • Container Image: Elixir 1.8
  • Elm: 0.19 (binary from GitHub release)

If you need any further info please let me know.

Thanks!

import nullable in examples

This is really minor, but seems like the example would be clearer if you also imported nullable from Json.Decode. Saw it used later in the examples and was confused for a bit/had to go back to the packages to see where it came from.

Cheers!

TODO in optionalDecoder

If you replace
Decode.fail (Decode.errorToString finalErr)
with
nullOr valDecoder
that should fulfil the TODO requirements.
Not an issue as such, I was just trying to understand the code and thought trying to solve this puzzle would help. And it did - I feel far less stupid than I did.

Decoding an object with an absent field

I couldn't figure out how to make a decoder which would give Nothing if either the field is absent or the value is null. Here is what I've tried implementing, but it doesn't quite work:

optional_ : String -> J.Decoder a -> J.Decoder (Maybe a -> b) -> J.Decoder b
optional_ key valDecoder decoder =
    DP.custom (optionalDecoderM (J.field key J.value) valDecoder) decoder


optionalDecoderM : J.Decoder J.Value -> J.Decoder a -> J.Decoder (Maybe a)
optionalDecoderM pathDecoder valDecoder =
    let
        handleResult input =
            case J.decodeValue pathDecoder input of
                Ok rawValue ->
                    case J.decodeValue valDecoder rawValue of
                        Ok finalResult ->
                            J.succeed (Just finalResult)

                        Err finalErr ->
                            J.succeed Nothing

                Err err ->
                    J.succeed Nothing
    in
    J.value
        |> J.andThen handleResult

I've then realized I don't know how to do this in simpler terms and opened an issue in elm/json: elm/json#7

But I decided to also open one here just because I am somewhat surprised that this is not a common use-case to have an API with inconsistent fields returned, and also because I think this functionality should be added in elm-json-decode-pipeline once we figure out how to do it. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.