Update part1 and part2
This commit is contained in:
3
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/.gitignore
vendored
Normal file
3
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Ignore build or dist files
|
||||
elm-stuff
|
||||
node_modules
|
||||
36
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/.travis.yml
vendored
Normal file
36
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/.travis.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
node_js: "node"
|
||||
os: linux
|
||||
env: ELM_VERSION=0.18.0
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- test/elm-stuff/build-artifacts
|
||||
- sysconfcpus
|
||||
|
||||
before_install:
|
||||
- echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
|
||||
- | # epic build time improvement - see https://github.com/elm-lang/elm-compiler/issues/1473#issuecomment-245704142
|
||||
if [ ! -d sysconfcpus/bin ];
|
||||
then
|
||||
git clone https://github.com/obmarg/libsysconfcpus.git;
|
||||
cd libsysconfcpus;
|
||||
./configure --prefix=$TRAVIS_BUILD_DIR/sysconfcpus;
|
||||
make && make install;
|
||||
cd ..;
|
||||
fi
|
||||
|
||||
install:
|
||||
- node --version
|
||||
- npm --version
|
||||
- cd tests
|
||||
- npm install -g elm@$ELM_VERSION
|
||||
- mv $(npm config get prefix)/bin/elm-make $(npm config get prefix)/bin/elm-make-old
|
||||
- printf '%s\n\n' '#!/bin/bash' 'echo "Running elm-make with sysconfcpus -n 2"' '$TRAVIS_BUILD_DIR/sysconfcpus/bin/sysconfcpus -n 2 elm-make-old "$@"' > $(npm config get prefix)/bin/elm-make
|
||||
- chmod +x $(npm config get prefix)/bin/elm-make
|
||||
- npm install
|
||||
- elm package install --yes
|
||||
|
||||
script:
|
||||
- npm test
|
||||
68
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/CHANGELOG.md
vendored
Normal file
68
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
### 2.6.0
|
||||
|
||||
**Additions:**
|
||||
- `keys` allows extracting _only_ the keys from a JSON object
|
||||
|
||||
### 2.5.0
|
||||
|
||||
**Additions:**
|
||||
- `dict` helps encoding `Dict`
|
||||
|
||||
### 2.4.0
|
||||
|
||||
**Additions:**
|
||||
- `collection` helps with decoding array-like JavaScript structures such as `HTMLCollection`
|
||||
- `combine` helps combining a `List` of decoders into a single `Decoder` for a `List` of such things
|
||||
|
||||
### 2.3.0
|
||||
|
||||
**Additions:**
|
||||
- `indexedList` to get access to the current js array index while decoding
|
||||
|
||||
**Other Stuff:**
|
||||
- `elm-doc-test` is now `elm-verify-examples`!
|
||||
|
||||
### 2.2.0
|
||||
|
||||
**Additions:**
|
||||
- `parseInt` and `parseFloat` for weird api's that return numbers as strings
|
||||
- `doubleEncoded` for a more generic _json as a string in json_ issues
|
||||
|
||||
**Fixes:**
|
||||
- `optionalField` decodes the field, rather than the surrounding object now.
|
||||
|
||||
**Other Stuff:**
|
||||
- Code Style conforms to elm-format@exp
|
||||
- Doc tests!
|
||||
- Travis integration
|
||||
|
||||
### 2.1.0
|
||||
|
||||
**Additions:**
|
||||
- `optionalField : String -> Json.Decode.Decoder a -> Json.Decode.Decoder (Maybe.Maybe a)` - Decode an optional field, succeeding with `Nothing` if it is missing, but still giving an error if it is malformed.
|
||||
|
||||
### 2.0.0
|
||||
|
||||
**Breaking Changes:**
|
||||
- Upgrade for Elm 0.18
|
||||
- Removed `maybeNull` in favor of `Json.Decode.nullable`
|
||||
- Removed `lazy` in favor of `Json.Decode.lazy`
|
||||
- Renamed `apply` to `andMap` and reversed arguments to `Decoder a -> Decoder (a -> b) -> Decoder b` to make it work nicely with `(|>)`
|
||||
|
||||
**Additions:**
|
||||
- `fromResult : Result String a -> Decoder a` - convert a `Result` to a `Decoder`, helpful in `andThen` callbacks following the removal of `Json.Decode.customDecoder`
|
||||
- `Json.Encode.Extra.maybe : (a -> Value) -> Maybe a -> Value` - encode a `Maybe a` given an encoder for `a`. Thanks to @hendore for this addition.
|
||||
|
||||
**Other Stuff:**
|
||||
- Code style conforms to elm-format
|
||||
|
||||
#### 1.1.0
|
||||
|
||||
**Additions:**
|
||||
- `Json.Decode.Extra.sequence` - lets you generate a list of `Decoder a` and attempt to apply them to a JSON list. _Authored by @cobalamin_
|
||||
|
||||
|
||||
#### 1.0.0
|
||||
|
||||
**Breaking Changes:**
|
||||
- Upgrade for Elm 0.17
|
||||
21
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/LICENSE
vendored
Normal file
21
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 CircuitHub Inc., Elm Community members
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
9
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/README.md
vendored
Normal file
9
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/README.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
[](https://travis-ci.org/elm-community/json-extra)
|
||||
|
||||
# json-extra
|
||||
|
||||
```
|
||||
elm-package install elm-community/json-extra
|
||||
```
|
||||
|
||||
Convenience functions for working with JSON
|
||||
61
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/docs/andMap.md
vendored
Normal file
61
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/docs/andMap.md
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
## Json.Decode.Extra.andMap
|
||||
|
||||
Imagine you have a data type for a user
|
||||
|
||||
```elm
|
||||
import Date (Date)
|
||||
|
||||
type alias User =
|
||||
{ id : Int
|
||||
, createdAt : Date
|
||||
, updatedAt : Date
|
||||
, deletedAt : Maybe Date
|
||||
, username : Maybe String
|
||||
, email : Maybe String
|
||||
, isAdmin : Bool
|
||||
}
|
||||
```
|
||||
|
||||
You can use `andMap` to incrementally apply decoders to your `User` type alias
|
||||
by using that type alias as a function. Recall that record type aliases are
|
||||
also functions which accept arguments in the order their fields are declared. In
|
||||
this case, `User` looks like
|
||||
|
||||
```elm
|
||||
User : Int -> Date -> Date -> Maybe Date -> Maybe String -> Maybe String -> Bool -> User
|
||||
```
|
||||
|
||||
And also recall that Elm functions can be partially applied. We can use these
|
||||
properties to apply each field of our JSON object to each field in our user one
|
||||
field at a time. All we need to do is also wrap `User` in a decoder and step
|
||||
through using `andMap`.
|
||||
|
||||
```elm
|
||||
userDecoder : Decoder User
|
||||
userDecoder =
|
||||
succeed User
|
||||
|> andMap (field "id" int)
|
||||
|> andMap (field "createdAt" date)
|
||||
|> andMap (field "updatedAt" date)
|
||||
|> andMap (field "deletedAt" (maybe date))
|
||||
|> andMap (field "username" (maybe string))
|
||||
|> andMap (field "email" (maybe string))
|
||||
|> andMap (field "isAdmin" bool)
|
||||
```
|
||||
|
||||
This is a shortened form of
|
||||
|
||||
```elm
|
||||
userDecoder : Decoder User
|
||||
userDecoder =
|
||||
succeed User
|
||||
|> andThen (\f -> map f (field "id" int))
|
||||
|> andThen (\f -> map f (field "createdAt" date))
|
||||
|> andThen (\f -> map f (field "updatedAt" date))
|
||||
|> andThen (\f -> map f (field "deletedAt" (maybe date)))
|
||||
|> andThen (\f -> map f (field "username" (maybe string)))
|
||||
|> andThen (\f -> map f (field "email" (maybe string)))
|
||||
|> andThen (\f -> map f (field "isAdmin" bool))
|
||||
```
|
||||
|
||||
See also: The [docs for `(|:)`](https://github.com/elm-community/json-extra/blob/master/docs/infixAndMap.md)
|
||||
131
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/docs/infixAndMap.md
vendored
Normal file
131
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/docs/infixAndMap.md
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
## Json.Decode.Extra.(|:)
|
||||
|
||||
|
||||
Infix version of `andMap` that makes for a nice DSL when decoding objects.
|
||||
|
||||
Consider the following type alias for a `Location`:
|
||||
|
||||
```elm
|
||||
type alias Location =
|
||||
{ id : Int
|
||||
, name : String
|
||||
, address : String
|
||||
}
|
||||
```
|
||||
|
||||
We can use `(|:)` to build up a decoder for `Location`:
|
||||
|
||||
```elm
|
||||
locationDecoder : Decoder Location
|
||||
locationDecoder =
|
||||
succeed Location
|
||||
|: (field "id" int)
|
||||
|: (field "name" string)
|
||||
|: (field "address" string)
|
||||
```
|
||||
|
||||
|
||||
|
||||
If you're curious, here's how this works behind the scenes, read on.
|
||||
|
||||
`Location` is a type alias, and type aliases give you a convenience function
|
||||
that returns an instance of the record in question. Try this out in `elm-repl`:
|
||||
|
||||
```elm
|
||||
> type alias Location = { id : Int, name: String, address: String }
|
||||
|
||||
> Location
|
||||
<function> : Int -> String -> String -> Repl.Location
|
||||
|
||||
> Location 1 "The White House" "1600 Pennsylvania Ave"
|
||||
{ id = 1, name = "The White House", address = "1600 Pennsylvania Ave" }
|
||||
```
|
||||
|
||||
In other words, if you call the `Location` function, passing three arguments,
|
||||
it will return a new `Location` record by filling in each of its fields. (The
|
||||
argument order is based on the order in which we listed the fields in the
|
||||
type alias; the first argument sets `id`, the second argument sets `name`, etc.)
|
||||
|
||||
Now try running this through `elm-repl`:
|
||||
|
||||
```elm
|
||||
> import Json.Decode exposing (succeed, int, string, field)
|
||||
|
||||
> succeed Location
|
||||
<function>
|
||||
: Json.Decode.Decoder
|
||||
(Int -> String -> String -> Repl.Location)
|
||||
```
|
||||
|
||||
So `succeed Location` gives us a `Decoder (Int -> String -> String -> Location)`.
|
||||
That's not what we want! What we want is a `Decoder Location`. All we have so
|
||||
far is a `Decoder` that wraps not a `Location`, but rather a function that
|
||||
returns a `Location`.
|
||||
|
||||
What `|: (field "id" int)` does is to take that wrapped function and pass an
|
||||
argument to it.
|
||||
|
||||
```elm
|
||||
> import Json.Decode exposing (succeed, int, string, field)
|
||||
|
||||
> (field "id" int)
|
||||
<function> : Json.Decode.Decoder Int
|
||||
|
||||
> succeed Location |: (field "id" int)
|
||||
<function>
|
||||
: Json.Decode.Decoder
|
||||
(String -> String -> Repl.Location)
|
||||
```
|
||||
|
||||
Notice how the wrapped function no longer takes an `Int` as its first argument.
|
||||
That's because `(|:)` went ahead and supplied one: the `Int` wrapped by the decoder
|
||||
`(field "id" int)` (which returns a `Decoder Int`).
|
||||
|
||||
Compare:
|
||||
|
||||
```elm
|
||||
> succeed Location
|
||||
Decoder (Int -> String -> String -> Location)
|
||||
|
||||
> succeed Location |: (field "id" int)
|
||||
Decoder (String -> String -> Location)
|
||||
```
|
||||
|
||||
We still want a `Decoder Location` and we still don't have it yet. Our decoder
|
||||
still wraps a function instead of a plain `Location`. However, that function is
|
||||
now smaller by one argument!
|
||||
|
||||
Let's repeat this pattern to provide the first `String` argument next.
|
||||
|
||||
```elm
|
||||
> succeed Location
|
||||
Decoder (Int -> String -> String -> Location)
|
||||
|
||||
> succeed Location |: (field "id" int)
|
||||
Decoder (String -> String -> Location)
|
||||
|
||||
> succeed Location |: (field "id" int) |: (field "name" string)
|
||||
Decoder (String -> Location)
|
||||
```
|
||||
|
||||
Smaller and smaller! Now we're down from `(Int -> String -> String -> Location)`
|
||||
to `(String -> Location)`. What happens if we repeat the pattern one more time?
|
||||
|
||||
```elm
|
||||
> succeed Location
|
||||
Decoder (Int -> String -> String -> Location)
|
||||
|
||||
> succeed Location |: (field "id" int)
|
||||
Decoder (String -> String -> Location)
|
||||
|
||||
> succeed Location |: (field "id" int) |: (field "name" string)
|
||||
Decoder (String -> Location)
|
||||
|
||||
> succeed Location |: (field "id" int) |: (field "name" string) |: (field "address" string)
|
||||
Decoder Location
|
||||
```
|
||||
|
||||
Having now supplied all three arguments to the wrapped function, it has ceased
|
||||
to be a function. It's now just a plain old `Location`, like we wanted all along.
|
||||
|
||||
We win!
|
||||
17
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/elm-package.json
vendored
Normal file
17
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/elm-package.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": "2.7.0",
|
||||
"summary": "Convenience functions for working with Json",
|
||||
"repository": "https://github.com/elm-community/json-extra.git",
|
||||
"license": "MIT",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"exposed-modules": [
|
||||
"Json.Decode.Extra",
|
||||
"Json.Encode.Extra"
|
||||
],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
2903
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/package-lock.json
generated
vendored
Normal file
2903
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/package.json
vendored
Normal file
9
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/package.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"scripts": {
|
||||
"test": "elm-verify-examples && elm-format --validate src"
|
||||
},
|
||||
"dependencies": {
|
||||
"elm-format": "^0.7.0-exp",
|
||||
"elm-verify-examples": "^2.3.1"
|
||||
}
|
||||
}
|
||||
565
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/src/Json/Decode/Extra.elm
vendored
Normal file
565
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/src/Json/Decode/Extra.elm
vendored
Normal file
@@ -0,0 +1,565 @@
|
||||
module Json.Decode.Extra
|
||||
exposing
|
||||
( (|:)
|
||||
, andMap
|
||||
, collection
|
||||
, combine
|
||||
, date
|
||||
, dict2
|
||||
, doubleEncoded
|
||||
, fromResult
|
||||
, indexedList
|
||||
, keys
|
||||
, optionalField
|
||||
, parseFloat
|
||||
, parseInt
|
||||
, sequence
|
||||
, set
|
||||
, when
|
||||
, withDefault
|
||||
)
|
||||
|
||||
{-| Convenience functions for working with Json
|
||||
|
||||
|
||||
# Date
|
||||
|
||||
@docs date
|
||||
|
||||
|
||||
# Incremental Decoding
|
||||
|
||||
@docs andMap, (|:)
|
||||
|
||||
|
||||
# Conditional Decoding
|
||||
|
||||
@docs when
|
||||
|
||||
|
||||
# List
|
||||
|
||||
@docs collection, sequence, combine, indexedList, keys
|
||||
|
||||
|
||||
# Set
|
||||
|
||||
@docs set
|
||||
|
||||
|
||||
# Dict
|
||||
|
||||
@docs dict2
|
||||
|
||||
|
||||
# Maybe
|
||||
|
||||
@docs withDefault, optionalField
|
||||
|
||||
|
||||
# Result
|
||||
|
||||
@docs fromResult
|
||||
|
||||
|
||||
# Encoded strings
|
||||
|
||||
@docs parseInt, parseFloat, doubleEncoded
|
||||
|
||||
-}
|
||||
|
||||
import Date
|
||||
import Dict exposing (Dict)
|
||||
import Json.Decode exposing (..)
|
||||
import Set exposing (Set)
|
||||
import String
|
||||
|
||||
|
||||
{-| Can be helpful when decoding large objects incrementally.
|
||||
|
||||
See [the `andMap` docs](https://github.com/elm-community/json-extra/blob/2.0.0/docs/andMap.md)
|
||||
for an explanation of how `andMap` works and how to use it.
|
||||
|
||||
-}
|
||||
andMap : Decoder a -> Decoder (a -> b) -> Decoder b
|
||||
andMap =
|
||||
map2 (|>)
|
||||
|
||||
|
||||
{-| Infix version of `andMap` that makes for a nice DSL when decoding objects.
|
||||
|
||||
See [the `(|:)` docs](https://github.com/elm-community/json-extra/blob/2.0.0/docs/infixAndMap.md)
|
||||
for an explanation of how `(|:)` works and how to use it.
|
||||
|
||||
-}
|
||||
(|:) : Decoder (a -> b) -> Decoder a -> Decoder b
|
||||
(|:) =
|
||||
flip andMap
|
||||
|
||||
|
||||
{-| Extract a date using [`Date.fromString`](http://package.elm-lang.org/packages/elm-lang/core/latest/Date#fromString)
|
||||
|
||||
import Date
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
""" "2012-04-23T18:25:43.511Z" """
|
||||
|> decodeString date
|
||||
--> Date.fromString "2012-04-23T18:25:43.511Z"
|
||||
|
||||
|
||||
""" "foo" """
|
||||
|> decodeString date
|
||||
--> Err "I ran into a `fail` decoder: Unable to parse 'foo' as a date. Dates must be in the ISO 8601 format."
|
||||
|
||||
-}
|
||||
date : Decoder Date.Date
|
||||
date =
|
||||
string
|
||||
|> andThen (Date.fromString >> fromResult)
|
||||
|
||||
|
||||
{-| Extract a set.
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
import Set
|
||||
|
||||
|
||||
"[ 1, 1, 5, 2 ]"
|
||||
|> decodeString (set int)
|
||||
--> Ok <| Set.fromList [ 1, 2, 5 ]
|
||||
|
||||
-}
|
||||
set : Decoder comparable -> Decoder (Set comparable)
|
||||
set decoder =
|
||||
list decoder
|
||||
|> map Set.fromList
|
||||
|
||||
|
||||
{-| Extract a dict using separate decoders for keys and values.
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
import Dict
|
||||
|
||||
|
||||
""" { "1": "foo", "2": "bar" } """
|
||||
|> decodeString (dict2 int string)
|
||||
--> Ok <| Dict.fromList [ ( 1, "foo" ), ( 2, "bar" ) ]
|
||||
|
||||
-}
|
||||
dict2 : Decoder comparable -> Decoder v -> Decoder (Dict comparable v)
|
||||
dict2 keyDecoder valueDecoder =
|
||||
keyValuePairs valueDecoder
|
||||
|> andThen (decodeDictFromTuples keyDecoder)
|
||||
|
||||
|
||||
{-| Helper function for dict
|
||||
-}
|
||||
decodeDictFromTuples : Decoder comparable -> List ( String, v ) -> Decoder (Dict comparable v)
|
||||
decodeDictFromTuples keyDecoder tuples =
|
||||
case tuples of
|
||||
[] ->
|
||||
succeed Dict.empty
|
||||
|
||||
( strKey, value ) :: rest ->
|
||||
case decodeString keyDecoder strKey of
|
||||
Ok key ->
|
||||
decodeDictFromTuples keyDecoder rest
|
||||
|> andThen (Dict.insert key value >> succeed)
|
||||
|
||||
Err error ->
|
||||
fail error
|
||||
|
||||
|
||||
{-| Try running the given decoder; if that fails, then succeed with the given
|
||||
fallback value.
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
""" { "children": "oops" } """
|
||||
|> decodeString (field "children" (list string) |> withDefault [])
|
||||
--> Ok []
|
||||
|
||||
|
||||
""" null """
|
||||
|> decodeString (field "children" (list string) |> withDefault [])
|
||||
--> Ok []
|
||||
|
||||
|
||||
""" 30 """
|
||||
|> decodeString (int |> withDefault 42)
|
||||
--> Ok 30
|
||||
|
||||
-}
|
||||
withDefault : a -> Decoder a -> Decoder a
|
||||
withDefault fallback decoder =
|
||||
maybe decoder
|
||||
|> map (Maybe.withDefault fallback)
|
||||
|
||||
|
||||
{-| If a field is missing, succeed with `Nothing`. If it is present, decode it
|
||||
as normal and wrap successes in a `Just`.
|
||||
|
||||
When decoding with
|
||||
[`maybe`](http://package.elm-lang.org/packages/elm-lang/core/latest/Json-Decode#maybe),
|
||||
if a field is present but malformed, you get a success and Nothing.
|
||||
`optionalField` gives you a failed decoding in that case, so you know
|
||||
you received malformed data.
|
||||
|
||||
Examples:
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
Let's define a `stuffDecoder` that extracts the `"stuff"` field, if it exists.
|
||||
|
||||
stuffDecoder : Decoder (Maybe String)
|
||||
stuffDecoder =
|
||||
optionalField "stuff" string
|
||||
|
||||
If the "stuff" field is missing, decode to Nothing.
|
||||
|
||||
""" { } """
|
||||
|> decodeString stuffDecoder
|
||||
--> Ok Nothing
|
||||
|
||||
If the "stuff" field is present but not a String, fail decoding.
|
||||
|
||||
""" { "stuff": [] } """
|
||||
|> decodeString stuffDecoder
|
||||
--> Err "Expecting a String at _.stuff but instead got: []"
|
||||
|
||||
If the "stuff" field is present and valid, decode to Just String.
|
||||
|
||||
""" { "stuff": "yay!" } """
|
||||
|> decodeString stuffDecoder
|
||||
--> Ok <| Just "yay!"
|
||||
|
||||
-}
|
||||
optionalField : String -> Decoder a -> Decoder (Maybe a)
|
||||
optionalField fieldName decoder =
|
||||
let
|
||||
finishDecoding json =
|
||||
case decodeValue (field fieldName value) json of
|
||||
Ok val ->
|
||||
-- The field is present, so run the decoder on it.
|
||||
map Just (field fieldName decoder)
|
||||
|
||||
Err _ ->
|
||||
-- The field was missing, which is fine!
|
||||
succeed Nothing
|
||||
in
|
||||
value
|
||||
|> andThen finishDecoding
|
||||
|
||||
|
||||
{-| This function turns a list of decoders into a decoder that returns a list.
|
||||
|
||||
The returned decoder will zip the list of decoders with a list of values,
|
||||
matching each decoder with exactly one value at the same position. This is most
|
||||
often useful in cases when you find yourself needing to dynamically generate a
|
||||
list of decoders based on some data, and decode some other data with this list
|
||||
of decoders.
|
||||
|
||||
Note that this function, unlike `List.map2`'s behaviour, expects the list of
|
||||
decoders to have the same length as the list of values in the JSON.
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
sequence
|
||||
[ map Just string
|
||||
, succeed Nothing
|
||||
, map Just string
|
||||
]
|
||||
|> flip decodeString """ [ "pick me", "ignore me", "and pick me" ] """
|
||||
--> Ok [ Just "pick me", Nothing, Just "and pick me" ]
|
||||
|
||||
-}
|
||||
sequence : List (Decoder a) -> Decoder (List a)
|
||||
sequence decoders =
|
||||
list value |> andThen (sequenceHelp decoders)
|
||||
|
||||
|
||||
{-| Helper function for sequence
|
||||
-}
|
||||
sequenceHelp : List (Decoder a) -> List Value -> Decoder (List a)
|
||||
sequenceHelp decoders jsonValues =
|
||||
if List.length jsonValues /= List.length decoders then
|
||||
fail "Number of decoders does not match number of values"
|
||||
else
|
||||
List.map2 decodeValue decoders jsonValues
|
||||
|> List.foldr (Result.map2 (::)) (Ok [])
|
||||
|> fromResult
|
||||
|
||||
|
||||
{-| Get access to the current index while decoding a list element.
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
repeatedStringDecoder : Int -> Decoder String
|
||||
repeatedStringDecoder times =
|
||||
string |> map (String.repeat times)
|
||||
|
||||
|
||||
""" [ "a", "b", "c", "d" ] """
|
||||
|> decodeString (indexedList repeatedStringDecoder)
|
||||
--> Ok [ "", "b", "cc", "ddd" ]
|
||||
|
||||
-}
|
||||
indexedList : (Int -> Decoder a) -> Decoder (List a)
|
||||
indexedList indexedDecoder =
|
||||
list value
|
||||
|> andThen
|
||||
(\values ->
|
||||
List.range 0 (List.length values - 1)
|
||||
|> List.map indexedDecoder
|
||||
|> sequence
|
||||
)
|
||||
|
||||
|
||||
{-| Get a list of the keys of a JSON object
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
""" { "alice": 42, "bob": 99 } """
|
||||
|> decodeString keys
|
||||
--> Ok [ "alice", "bob" ]
|
||||
|
||||
-}
|
||||
keys : Decoder (List String)
|
||||
keys =
|
||||
keyValuePairs (succeed ())
|
||||
|> map (List.foldl (\( key, _ ) acc -> key :: acc) [])
|
||||
|
||||
|
||||
{-| Transform a result into a decoder
|
||||
|
||||
Sometimes it can be useful to use functions that primarily operate on
|
||||
`Result` in decoders. An example of this is `Json.Decode.Extra.date`. It
|
||||
uses the built-in `Date.fromString` to parse a `String` as a `Date`, and
|
||||
then converts the `Result` from that conversion into a decoder which has
|
||||
either already succeeded or failed based on the outcome.
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
validateString : String -> Result String String
|
||||
validateString input =
|
||||
case input of
|
||||
"" ->
|
||||
Err "Empty string is not allowed"
|
||||
_ ->
|
||||
Ok input
|
||||
|
||||
|
||||
""" "something" """
|
||||
|> decodeString (string |> andThen (fromResult << validateString))
|
||||
--> Ok "something"
|
||||
|
||||
|
||||
""" "" """
|
||||
|> decodeString (string |> andThen (fromResult << validateString))
|
||||
--> Err "I ran into a `fail` decoder: Empty string is not allowed"
|
||||
|
||||
-}
|
||||
fromResult : Result String a -> Decoder a
|
||||
fromResult result =
|
||||
case result of
|
||||
Ok successValue ->
|
||||
succeed successValue
|
||||
|
||||
Err errorMessage ->
|
||||
fail errorMessage
|
||||
|
||||
|
||||
{-| Extract an int using [`String.toInt`](http://package.elm-lang.org/packages/elm-lang/core/latest/String#toInt)
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
""" { "field": "123" } """
|
||||
|> decodeString (field "field" parseInt)
|
||||
--> Ok 123
|
||||
|
||||
-}
|
||||
parseInt : Decoder Int
|
||||
parseInt =
|
||||
string |> andThen (String.toInt >> fromResult)
|
||||
|
||||
|
||||
{-| Extract a float using [`String.toFloat`](http://package.elm-lang.org/packages/elm-lang/core/latest/String#toFloat)
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
""" { "field": "50.5" } """
|
||||
|> decodeString (field "field" parseFloat)
|
||||
--> Ok 50.5
|
||||
|
||||
-}
|
||||
parseFloat : Decoder Float
|
||||
parseFloat =
|
||||
string |> andThen (String.toFloat >> fromResult)
|
||||
|
||||
|
||||
{-| Extract a JSON-encoded string field
|
||||
|
||||
"Yo dawg, I heard you like JSON..."
|
||||
|
||||
If someone has put JSON in your JSON (perhaps a JSON log entry, encoded
|
||||
as a string) this is the function you're looking for. Give it a decoder
|
||||
and it will return a new decoder that applies your decoder to a string
|
||||
field and yields the result (or fails if your decoder fails).
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
logEntriesDecoder : Decoder (List String)
|
||||
logEntriesDecoder =
|
||||
doubleEncoded (list string)
|
||||
|
||||
|
||||
logsDecoder : Decoder (List String)
|
||||
logsDecoder =
|
||||
field "logs" logEntriesDecoder
|
||||
|
||||
|
||||
""" { "logs": "[\\"log1\\", \\"log2\\"]"} """
|
||||
|> decodeString logsDecoder
|
||||
--> Ok [ "log1", "log2" ]
|
||||
|
||||
-}
|
||||
doubleEncoded : Decoder a -> Decoder a
|
||||
doubleEncoded decoder =
|
||||
string |> andThen (fromResult << decodeString decoder)
|
||||
|
||||
|
||||
{-| Helps converting a list of decoders into a decoder for a list of that type.
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
decoders : List (Decoder String)
|
||||
decoders =
|
||||
[ field "foo" string
|
||||
, field "bar" string
|
||||
, field "another" string
|
||||
]
|
||||
|
||||
|
||||
""" { "foo": "hello", "another": "!", "bar": "world" } """
|
||||
|> decodeString (combine decoders)
|
||||
--> Ok [ "hello", "world", "!" ]
|
||||
|
||||
-}
|
||||
combine : List (Decoder a) -> Decoder (List a)
|
||||
combine =
|
||||
List.foldr (map2 (::)) (succeed [])
|
||||
|
||||
|
||||
{-| Some JavaScript structures look like arrays, but aren't really. Examples
|
||||
include `HTMLCollection`, `NodeList` and everything else that has a `length`
|
||||
property, has values indexed by an integer key between 0 and `length`, but yet
|
||||
_is not_ a JavaScript Array.
|
||||
|
||||
This decoder can come to the rescue.
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
""" { "length": 3, "0": "foo", "1": "bar", "2": "baz" } """
|
||||
|> decodeString (collection string)
|
||||
--> Ok [ "foo", "bar", "baz" ]
|
||||
|
||||
-}
|
||||
collection : Decoder a -> Decoder (List a)
|
||||
collection decoder =
|
||||
field "length" int
|
||||
|> andThen
|
||||
(\length ->
|
||||
List.range 0 (length - 1)
|
||||
|> List.map (\index -> field (toString index) decoder)
|
||||
|> combine
|
||||
)
|
||||
|
||||
|
||||
{-| Helper for conditionally decoding values based on some discriminator
|
||||
that needs to pass a certain check.
|
||||
|
||||
import Json.Decode exposing (..)
|
||||
|
||||
|
||||
is : a -> a -> Bool
|
||||
is a b =
|
||||
a == b
|
||||
|
||||
|
||||
enabledValue : Decoder Int
|
||||
enabledValue =
|
||||
(field "value" int)
|
||||
|> when (field "enabled" bool) (is True)
|
||||
|
||||
|
||||
""" { "enabled": true, "value": 123 } """
|
||||
|> decodeString enabledValue
|
||||
--> Ok 123
|
||||
|
||||
|
||||
""" { "enabled": false, "value": 321 } """
|
||||
|> decodeString enabledValue
|
||||
--> Err "I ran into a `fail` decoder: Check failed with input `False`"
|
||||
|
||||
This can also be used to decode union types that are encoded with a discriminator field:
|
||||
|
||||
type Animal = Cat String | Dog String
|
||||
|
||||
|
||||
dog : Decoder Animal
|
||||
dog =
|
||||
map Dog (field "name" string)
|
||||
|
||||
|
||||
cat : Decoder Animal
|
||||
cat =
|
||||
map Cat (field "name" string)
|
||||
|
||||
|
||||
animalType : Decoder String
|
||||
animalType =
|
||||
field "type" string
|
||||
|
||||
|
||||
animal : Decoder Animal
|
||||
animal =
|
||||
oneOf
|
||||
[ when animalType (is "dog") dog
|
||||
, when animalType (is "cat") cat
|
||||
]
|
||||
|
||||
|
||||
"""
|
||||
[
|
||||
{ "type": "dog", "name": "Dawg" },
|
||||
{ "type": "cat", "name": "Roxy" }
|
||||
]
|
||||
"""
|
||||
|> decodeString (list animal)
|
||||
--> Ok [ Dog "Dawg", Cat "Roxy" ]
|
||||
|
||||
-}
|
||||
when : Decoder a -> (a -> Bool) -> Decoder b -> Decoder b
|
||||
when checkDecoder check passDecoder =
|
||||
checkDecoder
|
||||
|> andThen
|
||||
(\checkVal ->
|
||||
if check checkVal then
|
||||
passDecoder
|
||||
else
|
||||
fail <|
|
||||
"Check failed with input `"
|
||||
++ toString checkVal
|
||||
++ "`"
|
||||
)
|
||||
47
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/src/Json/Encode/Extra.elm
vendored
Normal file
47
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/src/Json/Encode/Extra.elm
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
module Json.Encode.Extra exposing (dict, maybe)
|
||||
|
||||
{-| Convenience functions for turning Elm values into Json values.
|
||||
|
||||
@docs dict, maybe
|
||||
|
||||
-}
|
||||
|
||||
import Dict exposing (Dict)
|
||||
import Json.Encode exposing (Value, encode, int, null, object)
|
||||
|
||||
|
||||
{-| Encode a Maybe value. If the value is `Nothing` it will be encoded as `null`
|
||||
|
||||
import Json.Encode exposing (..)
|
||||
|
||||
|
||||
maybe int (Just 50)
|
||||
--> int 50
|
||||
|
||||
|
||||
maybe int Nothing
|
||||
--> null
|
||||
|
||||
-}
|
||||
maybe : (a -> Value) -> Maybe a -> Value
|
||||
maybe encoder =
|
||||
Maybe.map encoder >> Maybe.withDefault null
|
||||
|
||||
|
||||
{-| Turn a `Dict` into a JSON object.
|
||||
|
||||
import Json.Encode exposing (..)
|
||||
import Dict
|
||||
|
||||
|
||||
Dict.fromList [ ( "Sue", 38 ), ( "Tom", 42 ) ]
|
||||
|> dict identity int
|
||||
|> encode 0
|
||||
--> """{"Sue":38,"Tom":42}"""
|
||||
|
||||
-}
|
||||
dict : (comparable -> String) -> (v -> Value) -> Dict comparable v -> Value
|
||||
dict toKey toValue dict =
|
||||
Dict.toList dict
|
||||
|> List.map (\( key, value ) -> ( toKey key, toValue value ))
|
||||
|> object
|
||||
16
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/tests/elm-package.json
vendored
Normal file
16
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/tests/elm-package.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "Test Suites",
|
||||
"repository": "https://github.com/elm-community/json-extra.git",
|
||||
"license": "MIT",
|
||||
"source-directories": [
|
||||
"../src",
|
||||
"."
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-community/elm-test": "4.0.0 <= v < 5.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
7
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/tests/elm-verify-examples.json
vendored
Normal file
7
part2/elm-stuff/packages/elm-community/json-extra/2.7.0/tests/elm-verify-examples.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"root": "../src",
|
||||
"tests": [
|
||||
"Json.Encode.Extra",
|
||||
"Json.Decode.Extra"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user