Skip to content

Instantly share code, notes, and snippets.

@danyx23
Created November 18, 2016 18:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danyx23/8d72a1e69ea4122495d3ca310c863cc6 to your computer and use it in GitHub Desktop.
Save danyx23/8d72a1e69ea4122495d3ca310c863cc6 to your computer and use it in GitHub Desktop.
Recursive Elm Json decoder crashes in Elm 0.18
module SwaggerMinimal exposing (..)
import Json.Decode
exposing
( int
, string
, float
, Decoder
, map
, oneOf
, andThen
, succeed
, dict
, lazy
, list
, field
, bool
, map2
, fail
)
import Json.Decode.Pipeline exposing (decode, required, optional, hardcoded, custom)
import Dict exposing (Dict)
type SchemaOrReference
= ReferencedSchema String
| SpecifiedSchema Schema
type DataType
= TypeInteger
| TypeFloat
| TypeString
| TypeBoolean
| TypeObject (Dict String SchemaOrReference)
| TypeArray SchemaOrReference
type alias Schema =
{ fieldType : DataType
, description : Maybe String
, xNullable : Bool
}
decodeSchemaOrReference : Decoder SchemaOrReference
decodeSchemaOrReference =
oneOf
[ map ReferencedSchema <| field "$ref" string
, map SpecifiedSchema decodeSchema
]
decodeSchema : Decoder Schema
decodeSchema =
field "type" string
|> andThen decodeSchemaByType
decodeSchemaByType : String -> Decoder Schema
decodeSchemaByType typeString =
let
typedDecoder =
case typeString of
"integer" ->
succeed TypeInteger
"float" ->
succeed TypeFloat
"double" ->
succeed TypeFloat
"string" ->
succeed TypeString
"boolean" ->
succeed TypeBoolean
"object" ->
map TypeObject <|
field "properties" <|
dict (lazy (\_ -> decodeSchemaOrReference))
"array" ->
map TypeArray <|
field "items" <|
(lazy (\_ -> decodeSchemaOrReference))
other ->
fail <| "Found unrecognized type " ++ other
fullDecoder =
decode Schema
|> custom typedDecoder
|> optional "description" (map Just string) Nothing
|> optional "x-nullable" bool False
in
fullDecoder
module Tests exposing (..)
import Test exposing (..)
import Expect
import SwaggerMinimal
import Json.Decode exposing (decodeString)
all : Test
all =
describe "Swagger decoder tests"
[ describe "Single decoder test"
[ test "test SchemaOrReference" <|
\() ->
let
decodeResult =
decodeString SwaggerMinimal.decodeSchemaOrReference definitionJson
( resultOk, message ) =
isResultOk decodeResult
in
Expect.true "SchemaOrReference is resul ok" resultOk
|> Expect.onFail message
]
]
isResultOk : Result String a -> ( Bool, String )
isResultOk result =
case result of
Result.Ok _ ->
( True, "" )
Err error ->
( False, error )
definitionJson =
"""{
"properties": {
"buckets": {
"description": "Aggregation values (buckets) and correspondig item counts",
"items": {
"$ref": "#/definitions/AggregationBucket"
},
"type": "array"
},
"filterTerm": {
"description": "Term used to filter the results",
"type": "string"
},
"name": {
"description": "Aggregation name",
"type": "string"
}
},
"type": "object"
}
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment