BSON

 view release on metacpan or  search on metacpan

lib/BSON.pm  view on Meta::CPAN

#pod
#pod     use JSON::MaybeXS;
#pod     my $ext = BSON->perl_to_extjson($data, \%options);
#pod     my $json = encode_json($ext);
#pod
#pod Takes a perl data structure (i.e. hashref) and turns it into an
#pod L<MongoDB Extended JSON|https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>
#pod structure. Note that the structure will still have to be serialized.
#pod
#pod Possible options are:
#pod
#pod =for :list
#pod * C<relaxed> A boolean indicating if "relaxed extended JSON" should
#pod be generated. If not set, the default value is taken from the
#pod C<BSON_EXTJSON_RELAXED> environment variable.
#pod
#pod =cut

my $use_win32_specials = ($^O eq 'MSWin32' && $] lt "5.022");

my $is_inf = $use_win32_specials ? qr/^1.\#INF/i : qr/^inf/i;
my $is_ninf = $use_win32_specials ? qr/^-1.\#INF/i : qr/^-inf/i;
my $is_nan = $use_win32_specials ? qr/^-?1.\#(?:IND|QNAN)/i : qr/^-?nan/i;

sub perl_to_extjson {
    my ($class, $data, $options) = @_;

    local $ENV{BSON_EXTJSON} = 1;
    local $ENV{BSON_EXTJSON_RELAXED} = $ENV{BSON_EXTJSON_RELAXED};
    $ENV{BSON_EXTJSON_RELAXED} = $options->{relaxed};

    if (not defined $data) {
        return undef; ## no critic
    }

    if (blessed($data) and $data->can('TO_JSON')) {
        my $json_data = $data->TO_JSON;
        return $json_data;
    }

    if (not ref $data) {

        if (looks_like_number($data)) {
            if ($ENV{BSON_EXTJSON_RELAXED}) {
                return $data;
            }

            if ($data =~ m{\A-?[0-9_]+\z}) {
                if ($data <= $max_int32) {
                    return { '$numberInt' => "$data" };
                }
                else {
                    return { '$numberLong' => "$data" };
                }
            }
            else {
                return { '$numberDouble' => 'Infinity' }
                    if $data =~ $is_inf;
                return { '$numberDouble' => '-Infinity' }
                    if $data =~ $is_ninf;
                return { '$numberDouble' => 'NaN' }
                    if $data =~ $is_nan;
                my $value = "$data";
                $value = $value / 1.0;
                return { '$numberDouble' => "$value" };
            }
        }

        return $data;
    }

    if (boolean::isBoolean($data)) {
        return $data;
    }

    if (ref $data eq 'HASH') {
        for my $key (keys %$data) {
            my $value = $data->{$key};
            $data->{$key} = $class->perl_to_extjson($value, $options);
        }
        return $data;
    }

    if (ref $data eq 'ARRAY') {
        for my $index (0 .. $#$data) {
            my $value = $data->[$index];
            $data->[$index] = $class->perl_to_extjson($value, $options);
        }
        return $data;
    }

    if (blessed($data) and $data->isa('JSON::PP::Boolean')) {
        return $data;
    }

    if (
        blessed($data) and (
            $data->isa('Math::BigInt') or
            $data->isa('Math::BigFloat')
        )
    ) {
        return $data;
    }

    die sprintf "Unsupported ref value (%s)", ref($data);
}

#pod =method extjson_to_perl
#pod
#pod     use JSON::MaybeXS;
#pod     my $ext = decode_json($json);
#pod     my $data = $bson->extjson_to_perl($ext);
#pod
#pod Takes an
#pod L<MongoDB Extended JSON|https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>
#pod data structure and inflates it into a Perl data structure. Note that
#pod you have to decode the JSON string manually beforehand.
#pod
#pod Canonically specified numerical values like C<{"$numberInt":"23"}> will
#pod be inflated into their respective C<BSON::*> wrapper types. Plain numeric
#pod values will be left as-is.



( run in 1.266 second using v1.01-cache-2.11-cpan-9581c071862 )