LINUX.ORG.RU

Покритикуйте мою сериализацию в JSON

 , ,


1

2

Понадобилось написать самобытную сериализацию в JSON. Пока вот так:

# Poor man's JSON
sub serialize {
    my ($obj) = @_;
    my $result;

    if (ref $obj eq 'HASH') {
        $result = sprintf( '{ %s }', join(', ', map {
            sprintf '"%s": %s', $_, serialize($obj->{$_})
        } keys %$obj));
    } elsif (ref $obj eq 'ARRAY') {
        $result = sprintf('[ %s ]', join(', ', map { serialize($_) } @$obj));
    } elsif (!ref $obj) {
        if ($obj =~ /^\d+$/) {
            $result = $obj;
        } else {
            $obj =~ s/(["\\])/\\$1/g;
            $obj =~ s/\r/\\r/g;
            $obj =~ s/\n/\\n/g;
            $obj =~ s/\t/\\t/g;
            $result = sprintf('"%s"', $obj);
        }
    }

    return $result;
}

Ответ на: комментарий от KennyMinigun

По спецификации числа в JSON не имеют ограничения по длинне.

По спецификации числа в JSON могут иметь и дробную часть, и экспоненту, и знак.

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 1)
Ответ на: комментарий от theNamelessOne

но разве оно совпадет с форматами 1.1 .1 1. 1/2 1,2 и тп?

Из приведённого только 1.1 является корректным числом в JSON.

theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Переписал:

} elsif ($obj =~ /^ -? \d+ (?:\.\d+)? (?:e[+-]\d+)? $/x) {
    $result = $obj;
}

Заодно обнаружил багофичу Perl:

12.34e-5.7 == 0.00012347

KennyMinigun ★★★★★
() автор топика
Ответ на: комментарий от KennyMinigun

Кстати «юнит-тест», если кому интересно:

#!/usr/bin/env perl

use strict;
use warnings;

my @numbers = (
    1,
    2.3,
    2e+3,
    4.5e+4,
    0.89e-5,
    12.34e-56,
    12.34E-56,
    12.34e-5.7,
    88e-44,
    11e-13.66,
    0.1,
    -10,
    -0.4,
    -6.3e-7,
    'aaa',
    '10aa10',
    '10.10aaa',
    'a11e-11',
    'b88.3e-44'
);

for my $n (@numbers) {
    print "$n : ";
    if ($n =~ /^ -? \d+ (?:\.\d+)? (?:e[+-]\d+)? $/x) {
        print "NUMBER";
    } else {
        print "NOT NUMBER";
    }
    print "\n";
}

KennyMinigun ★★★★★
() автор топика
Ответ на: комментарий от KennyMinigun

Кстати «юнит-тест», если кому интересно:

Вот примеры, на которых твоя регулярка валится:

  • 042 — должно быть NOT NUMBER;
  • 42e42 — должно быть NUMBER;
  • 42.42E42 — должно быть NUMBER.
theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Починил. Спасибо

/^ -? (?:0|[1-9]\d*) (?:\.\d+)? (?:[eE][+-]?\d+)? $/x

KennyMinigun ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.