New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

json decoding: undefined is not a function #471

Closed
gpaul opened this Issue Jan 5, 2016 · 6 comments

Comments

Projects
None yet
3 participants
@gpaul

gpaul commented Jan 5, 2016

When parsing json into an algebraic datatype with Json.Decode.customDecoder and 'oneOf' I get the following error:
"expecting one of the following:\n undefined is not a function\n expecting a String but got {"aaa":"1"}"

The code follows:

import Graphics.Element exposing (show)
import Dict exposing (Dict)
import Json.Decode exposing ((:=), succeed, object2, list, string, bool, dict, int, maybe, decodeString, map, value, Decoder, customDecoder, oneOf)

jsonString = """{"aaa": "1"}"""

type V = Str String
            | Object (Dict String V)

stringer : String -> Result String V
stringer s = Ok (Str s)

stringer2 : Decoder V
stringer2 = customDecoder string stringer

objecter : Decoder (Dict String V)
objecter = dict decodeV

objecter2 : Decoder V
objecter2 = customDecoder objecter objecter3

objecter3 : (Dict String V) -> Result String V
objecter3 d = Ok (Object d)

decodeV = oneOf
    [
    objecter2
    , stringer2
    ]

main =
 case (decodeString decodeV jsonString) of
     Ok value -> show value
     Err msg -> show msg

@gpaul gpaul changed the title from undefined is not a function to json decoding: undefined is not a function Jan 5, 2016

@gpaul

This comment has been minimized.

Show comment
Hide comment
@gpaul

gpaul Jan 5, 2016

The generated code looks like this. Could it be an order of initialization issue, where decodeV references objecter2, which references objecter, which references decodeV again?

   var Object = function (a) {
      return {ctor: "Object"
             ,_0: a};
   };
   var objecter3 = function (d) {
      return $Result.Ok(Object(d));
   };
   var Str = function (a) {
      return {ctor: "Str",_0: a};
   };
   var stringer = function (s) {
      return $Result.Ok(Str(s));
   };
   var stringer2 = A2($Json$Decode.customDecoder,
   $Json$Decode.string,
   stringer);
   var objecter2 = A2($Json$Decode.customDecoder,
   objecter,
   objecter3);
   var objecter = $Json$Decode.dict(decodeV);
   var decodeV = $Json$Decode.oneOf(_L.fromArray([objecter2
                                                 ,stringer2]));

gpaul commented Jan 5, 2016

The generated code looks like this. Could it be an order of initialization issue, where decodeV references objecter2, which references objecter, which references decodeV again?

   var Object = function (a) {
      return {ctor: "Object"
             ,_0: a};
   };
   var objecter3 = function (d) {
      return $Result.Ok(Object(d));
   };
   var Str = function (a) {
      return {ctor: "Str",_0: a};
   };
   var stringer = function (s) {
      return $Result.Ok(Str(s));
   };
   var stringer2 = A2($Json$Decode.customDecoder,
   $Json$Decode.string,
   stringer);
   var objecter2 = A2($Json$Decode.customDecoder,
   objecter,
   objecter3);
   var objecter = $Json$Decode.dict(decodeV);
   var decodeV = $Json$Decode.oneOf(_L.fromArray([objecter2
                                                 ,stringer2]));
@jvoigtlaender

This comment has been minimized.

Show comment
Hide comment
@jvoigtlaender

jvoigtlaender Jan 5, 2016

Contributor

See elm/compiler#873 and the various issues occurring as links there that are related to Json.Decode specifically. For example, https://github.com/elm-lang/core/issues/361 and elm/compiler#1244.

So yes, the cause here is the recursive dependencies. And it is well known that it is an issue that should be fixed. If you need a workaround as long as it is not yet fixed, I think the discussion in https://github.com/elm-lang/core/issues/361 (about introducing dummy arguments to delay evaluation) might help you.

Contributor

jvoigtlaender commented Jan 5, 2016

See elm/compiler#873 and the various issues occurring as links there that are related to Json.Decode specifically. For example, https://github.com/elm-lang/core/issues/361 and elm/compiler#1244.

So yes, the cause here is the recursive dependencies. And it is well known that it is an issue that should be fixed. If you need a workaround as long as it is not yet fixed, I think the discussion in https://github.com/elm-lang/core/issues/361 (about introducing dummy arguments to delay evaluation) might help you.

@gpaul

This comment has been minimized.

Show comment
Hide comment
@gpaul

gpaul Jan 6, 2016

Thanks, that works perfectly. Feel free to close this ticket.

gpaul commented Jan 6, 2016

Thanks, that works perfectly. Feel free to close this ticket.

@awalterschulze

This comment has been minimized.

Show comment
Hide comment
@awalterschulze

awalterschulze Jan 6, 2016

So for future reference:
objecter2 becomes

objecter2 : () -> Decoder V
objecter2 () = customDecoder objecter objecter3

And decodeV becomes

decodeV () = oneOf
    [
    objecter2 ()
    , stringer2
    ]

And main becomes

main =
 case (decodeString (decodeV ()) jsonString) of
     Ok value -> show value
     Err msg -> show msg

Is this correct?

awalterschulze commented Jan 6, 2016

So for future reference:
objecter2 becomes

objecter2 : () -> Decoder V
objecter2 () = customDecoder objecter objecter3

And decodeV becomes

decodeV () = oneOf
    [
    objecter2 ()
    , stringer2
    ]

And main becomes

main =
 case (decodeString (decodeV ()) jsonString) of
     Ok value -> show value
     Err msg -> show msg

Is this correct?

@jvoigtlaender

This comment has been minimized.

Show comment
Hide comment
@jvoigtlaender

jvoigtlaender Jan 6, 2016

Contributor

Yes, plus a corresponding change to the use of decodeV in objecter.

Contributor

jvoigtlaender commented Jan 6, 2016

Yes, plus a corresponding change to the use of decodeV in objecter.

@awalterschulze

This comment has been minimized.

Show comment
Hide comment
@awalterschulze

awalterschulze Jan 6, 2016

Ah yes good catch

objecter : Decoder (Dict String V)
objecter = dict (decodeV ())

awalterschulze commented Jan 6, 2016

Ah yes good catch

objecter : Decoder (Dict String V)
objecter = dict (decodeV ())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment