Как преобразовать объекты Perl в JSON и наоборот - PullRequest
21 голосов
/ 15 ноября 2010

Я определил объект Point в файле Point.pm следующим образом:

package Point;
sub new {
    my ($class) = @_;
    my $self = {
        _x => 0,
        _y => 0,
    };
    return bless $self => $class;
}

sub X {
    my ($self, $x) = @_;
    $self->{_x} = $x if defined $x;
    return $self->{_x};
}

sub Y {
    my ($self, $y) = @_;
    $self->{_y} = $y if defined $y;
    return $self->{_y};
}

1;

Теперь, когда я использую JSON , чтобы преобразовать объект в JSON следующим кодом:

use JSON;
use Point;

Point $p = new Point;
$p->X(20);
$p->Y(30);

my $json = encode_json $p;

Я получаю следующую ошибку:

encountered object 'Point=HASH(0x40017288)', but neither allow_blessed nor convert_blessed settings are enabled at test.pl line 28

Как преобразовать JSON в и из объекта в объект с помощью модуля JSON?

Ответы [ 4 ]

21 голосов
/ 15 ноября 2010

Предупреждение говорит вам о том, что не так. Если вы не скажете JSON, как обрабатывать благословенные ссылки (объекты Perl), JSON дескрипторы только неблаженные структуры данных.

Вы можете convert_blessed, и вы можете allow_blessed. Для allow_blessed написано:

Если $enable равно false (по умолчанию), то при кодировании будет выдано исключение при обнаружении благословенного объекта.

Точка является классом объекта, поэтому экземпляр Point является благословенной ссылкой, и, следовательно, по умолчанию для JSON выбрасывается исключение.

Если вы включите convert_blessed, он вызовет метод TO_JSON для вашего объекта. С простыми объектами, такими как Point (которые не содержат благословенных членов), вы можете сделать это так же просто, как:

sub TO_JSON { return { %{ shift() } }; }

Если вам придется спуститься по структуре, она получит лот хайриер.


Кто-то в комментариях ниже сказал, что я не рассказал, как получить объекты из из JSON.

Основы просты. Итак, вот идет

my $object = bless( JSON->new->decode( $json_string ), 'ClassIWant' );

В основном я рассмотрел ту часть, которая не позволяет просто сериализовать благословенный объект в JSON.

Основы десериализации просты, как и основы сериализации просты - как только вы знаете хитрость. На этом пути нет ошибок, есть только задача найти то, что вам нужно, и благословить его в нужном классе.

Если вы хотите, чтобы код был связан с объектами, тогда вы будете знать, что должно быть благословлено и во что оно должно быть благословлено. Если вам нужен полностью отделенный код, это не сложнее и проще в Perl, чем в самом JavaScript .

Вам нужно будет сериализовать маркер в JSON. Если мне нужно что-то вроде этого, я вставлю поле '__CLASS__' в благословенные объекты. И при десериализации я спущусь через структуру и благословлю все, как это:

 bless( $ref, delete $ref->{__CLASS__} );

Но, как я уже сказал, в Perl это не легче и не сложнее, потому что JSON представляет одну и ту же проблему для всех языков.

Как Шверн предложил в своем комментарии к началу, YAML гораздо лучше построен для сериализации и десериализации объектов, потому что он имеет обозначение для него. JSON предоставляет ассоциативные массивы или массивы.

5 голосов
/ 15 ноября 2010

Вы пытались прочитать документацию JSON в параметрах allow_blessed и convert_blessed , как указано в сообщении об ошибке?Это должно объяснить, как преобразовать объект Perl в JSON.

Труднее пойти другим путем, поскольку JSON не YAML и не предназначен для десериализации в класс.основанная система объектов, как в Perl.Вы можете поэкспериментировать с опциями filter_json_object или filter_json_single_key_object , или вы можете постобработать декодированный JSON и создать объекты самостоятельно.

3 голосов
/ 15 ноября 2010

Вам нужно JSYNC .

use JSYNC;
use Point;
my $p = Point->new;
$p->X(20);
$p->Y(30);

my $jsync = JSYNC::dump($p, {pretty => 1});

{
   "!" : "!perl/hash:Point",
   "_x" : "20",
   "_y" : "30"
}
2 голосов
/ 15 ноября 2010

Может оказаться полезным преобразовать ваши классы в Moose и использовать MooseX :: Storage для их сериализации и десериализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...