#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use IO::String; use bytes; my $bio = IO::String->new; # binary IO $bio->binmode(); my $h = { 'nix' => '', 'root' => { 1 => { '1.1' => 'val_1.1', '1.2' => 'val_1.2', '1.3' => { '1.3.1' => 'val_1.3.1', '1.3.2' => 'val_1.3.2', }, }, 2 => 'val_2', 'Umlaute in UTF-8' => 'äöüß', }, 'nochn_root' => 'hat_nur_einen_Value', }; ##################### serialize ########################################### while( my($k, $v) = each %{$h}){ serializer($k,$v); } sub serializer{ my $key = shift; my $stub = shift; my @bis = @_; if(ref $stub eq 'HASH'){ push @bis, $key; while(my($stubk, $stubv) = each %{$stub}){ serializer($stubk, $stubv, @bis); } } else{ if(scalar @bis){ # zum Angucken # printf "%s => %s => %s\n", join(" => ", @bis), $key, $stub; # Algorithmus: # Anzahl der Keys als N # dann das Array mit den Keys # zuletzt der Value my $xbis = scalar(@bis); $bio->print(pack('N', $xbis + 1)); foreach my $k(@bis){ $bio->print(pack('N', length($k)).$k); } # der letzte key vor dem Value $bio->print(pack('N', length($key)).$key); $bio->print(pack('N', length($stub)).$stub); } else{ # zum Angucken # printf "%s => %s\n", $key, $stub; $bio->print(pack('N', 1)); $bio->print(pack('N', length($key)).$key); $bio->print(pack('N', length($stub)).$stub); } } } #################### de-serialize ######################################### $bio->seek(0,0); my $result = {}; # Die Schleife läuft über die Anzahl der Keys: 4 byte while(my $buffer = fread(4)){ my $xkeys = unpack('N', $buffer); my @prekeys = (); foreach my $i(1..$xkeys){ my $buffer = fread(4); my $lenpk = unpack 'N', $buffer; my $pk = $lenpk ? fread($lenpk) : ''; push @prekeys, $pk; } # jetzt den Wert auslesen my $vlen = unpack('N', fread(4)); my $val = $vlen ? fread($vlen) : ''; stacker(\@prekeys, $result, $val); } # Ergebnis ausgeben print Dumper $h, $result; # keys als Referenzen aufeinander stocken # der letzte Key bekommt den Wert sub stacker{ my ($ref, $hash, $val) = @_; my $last = pop @$ref; for my $el (@$ref) { $hash = $hash->{$el} ||= {}; } $hash->{$last} = $val; } # wrapper für read, buffer as return-value sub fread{ my $len = shift; read($bio, my $buffer, $len); return $buffer; }