Perl для преобразования данных в формат JSON

#json #perl

#json #perl

Вопрос:

У меня проблема с преобразованием моих данных в json, и я не знаю почему.

Вот некоторый код, который работает:

 #constructor
sub new {
  my $class = shift;
  my $Titel = shift;
  my $Text = shift;
  my $Time = localtime;
  my $self = {};

  $self->{text} = $Text;
  $self->{create} = $Time;
  $self->{edit} = $Time;

  my $json = JSON::XS->new();

  open WF, '>> $file' || die "Error : $!";
  print WF $json->encode($self)."n";
  close WF;

  bless $self, $class;
}
  

Я создаю ‘object’ и сохраняю данные также в текстовом файле (через JSON).

У меня возникают проблемы, если я пытаюсь отредактировать некоторые данные:

 sub edit {
my $self = shift;
my $Text = shift;
my $ID = shift;
my $Time = localtime;
my $json = JSON::XS->new();
$json->allow_blessed(1);

$self->{text} = $Text; #edit text
$self->{edit} = $Time; # edit date

open INPUT, '< $file' || die "Error : $!";
my @data = <INPUT>;
close(INPUT);

open WF, '> $file' || die "Error : $!";

for (my $Count=0; $Count<=$#data; $Count  ){
    chomp($data[$Count]);

    if($Count == $ID){#if line of data found, who is going to be edited
        print WF $json->encode($self)."n";
    }else{
        print WF $data[$Count]."n";
    }
}

close WF;
}
  

Что я пытаюсь сделать, так это отредактировать всего одну строку в текстовом файле.. (если у вас есть идея получше, пожалуйста, покажите мне: D)

Я не вижу разницы между моей процедурой в коде, показанном первым, и этой….

он просто записывает «null» обратно в текстовый файл…

Есть идеи?

Комментарии:

1. Вам нужно использовать двойные кавычки вокруг вашего второго аргумента to open , поскольку имеющиеся у вас сейчас одинарные кавычки не будут интерполировать $file переменную. Еще лучше использовать форму с тремя аргументами open INPUT, '<', $file

2. Моя проблема в том, что он записывает «null» обратно в строку —> print WF $ json-> encode($ self).» n»;<— я могу открыть файл и так далее (я отредактировал код .. неправильно. извините:D в моем исходном коде указан путь, а не ‘$ file’. не знал этого)

3. Вызывается ли «дополнительное редактирование» как метод? т.е. «$thing-> edit ()»?

4. да. я отладил его, и $ self является правильным, когда я вызываю метод редактирования. я также могу редактировать значения в своей программе. не будет работать только обратная запись в текстовый файл (ТОЛЬКО в нижнем фрагменте кода! в верхнем он работает отлично).

Ответ №1:

Я не эксперт по JSON, но у encode метода возникли проблемы с благословенной ссылкой. Использование неиспользованной ссылки кажется допустимым обходным путем:

 if($Count == $ID){#if line of data found, who is going to be edited
    print WF $json->encode( {%$self} )."n";
...
  

Комментарии:

1. Вот почему я включил это —> $ json-> allow_blessed(1);<— ваш код не будет работать, в любом случае спасибо за вашу помощь.

2. хм, но ваше право … были проблемы из-за благословенной ссылки… я сохранил данные в скалярном формате tmp и закодировал его… теперь это работает. спасибо :))

3. Просматривая JSON документы, JSON::allow_blessed будет подавлять исключения при передаче объекта blessed в encode . Но для кодирования благословенного объекта требуется, чтобы вы (1) также вызвали $json->convert_blessed(1) и (2) реализовали TO_JSON метод object, который возвращает значение для encode. Это значение также должно быть неиспользованной ссылкой.

Ответ №2:

Я поддерживаю идею (как вы уже поняли), что проблема заключается в благословенной ссылке, однако я предлагаю вам другое решение (в конце концов, это Perl: TIMTOWTDI). Модуль Acme::Damn позволяет разблокировать (то есть проклясть) объект. Поэтому вы должны уметь:

 print WF $json->encode(damn($self))."n";
  

Также я почувствовал, что должен поделиться, поскольку у метода такое умное название.

Ответ №3:

Следуя предложению последнего mob, вот простой пример того, как сериализовать благословенные ссылки.

 package Node;

sub new {
    my $class = shift;
    bless { @_ }, $class;
}

sub TO_JSON {
    my $self = shift;
    return { class => 'Node', data => { %$self } };
}

package main;

use JSON;

my $node_hash = {
    a => [ 'text1', 'text2' ],
    b => [ 'what',  'is', 'this' ],
    c => [ Node->new(some => 'data') ],
};

print to_json($node_hash, { convert_blessed => 1 });
  

Однако вам нужно обратить внимание на декодирование. Можно использовать filter_json_single_key_object для реализации полного цикла.