sectokia has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, Given 'mylib/json.pm':
package mylib::json; use Exporter 'import'; our @EXPORT=qw(jsonEncode); use JSON::XS; sub jsonEncode($) { my ($o) = @_; my $j = undef; eval { $j = JSON::XS->new->encode($o); }; return $@ ? undef : $j; }
And 'mylib.pm':
package mylib; use Exporter 'import'; use lib 'mylib'; use mylib::json; our @EXPORT = ( @mylib::json::EXPORT );
Then the following 'test.pl' works fine:
use strict; use warnings; use lib '.'; use mylib; print jsonEncode({foo => 'bar'});
However once I add 'use JSON::WebToken' module I get an issue:
use strict; use warnings; use lib '.'; use mylib; use JSON::WebToken; print jsonEncode({foo => 'bar'});

This warns:

Attempt to call undefined import method with arguments ("encode_json" +...) via package "JSON" (Perhaps you forgot to load the package?) at +C:/Strawberry/perl/site/lib/JSON/WebToken.pm line 12.

I don't understand what I am doing with mylib that impacts what JSON::WebToken does? Without mylib JSON::WebToken is working fine.

Replies are listed 'Best First'.
Re: Undefined import name priority issue?
by hv (Prior) on Apr 08, 2025 at 03:00 UTC

    Line 12 of JSON::WebToken is:

    use JSON qw(encode_json decode_json);

    Perl's use statement is shorthand for:

    BEGIN { require JSON; JSON->import(qw(encode_json decode_json)); }

    .. and the key feature of require is that it loads the module only if it has not already been loaded. It checks that by looking in %INC.

    My guess then is that JSON::XS is poking a value into %INC to make it look as if JSON itself has also already been loaded - but failing to define the JSON::import() method.

    In the JSON::XS SYNOPSIS section I see:

    # Note that JSON version 2.0 and above will automatically use JSON:: +XS # if available, at virtually no speed overhead either, so you should # be able to just: use JSON; # and do the same things, except that you have a pure-perl fallback +now.

    .. so I suspect if you change your mylib::json to use JSON instead of use JSON::XS, it will probably make the problem disappear. If my diagnosis is correct, though, I'd call this a bug in JSON::XS.

      The issue seems to be the existance of a file in mylib with name 'json.pm'

      The problem surface even with this extremely simple setup:

      mylib/json.pm:

      package mylib::json;1;

      mylib.pm:

      package mylib; use lib 'mylib'; 1;

      test.pl:

      use strict; use warnings; use lib '.'; use mylib; use JSON::WebToken;

      output:

      Attempt to call undefined import method with arguments ("encode_json" +...) via package "JSON" (Perhaps you forgot to load the package?) at +C:/Strawberry/perl/site/lib/JSON/WebToken.pm line 12.

      I assume JSON::WebToken or JSON/JSON::XS is looking in path for json.pm file and getting confused? As long as I don't use the name json.pm there is no problem.

        The issue seems to be the existance of a file in mylib with name 'json.pm'

        No, half of the issue is that you are doing this:

        use lib 'mylib'; use mylib::json;

        You add the "mylib" directory to the module search path (@INC). In that case, your module should be simply named json and not mylib::json. If you want to load it as mylib::json, don't add the "mylib" directory to @INC, but the directory containing the "mylib" directory (i.e. "."). Older perls already include "." in @INC, that's why it probably works at all.

        The second part of the issue is that your filesystem is not case sensitive. Do you see any difference between json and JSON? I see four different bits, but your filesystem does not. So when perl attempts to load "JSON.pm" containing the JSON package, it is fed "json.pm" containing the mylib::json package instead.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

        You are on MS Windows where the default filesystem is case insensitive. Blame Microsoft (again).


        🦛