kusanagi / katana-sdk-php7

PHP7 SDK for the KATANA Framework
https://kusanagi.io
MIT License
5 stars 2 forks source link

Analyse encoding of arrays in msgpack #106

Open fcastilloes opened 6 years ago

fcastilloes commented 6 years ago

Msgpack supports both maps and arrays for lists of data. When a packing is done from php, a map could be created both with string or integer keys. An msgpack array is created when the php array has only integer keys that are sequential and starting from 0.

Katana has strong types and map keys must be strings, so any integer key in a map will result in error.

Some solution is needed to prevent those errors.

The library could have some options. https://github.com/rybakit/msgpack.php#type-detection-mode

rybakit commented 6 years ago

@fcastilloes It's quite easy to achieve with the new msgpack.php v0.3.0:

First, create a "packable" type transformer:

class StringKeyMapTransformer implements Packable
{
    public function pack(Packer $packer, $value)
    {
        if (!$value instanceof Map) {
            return null;
        }

        $data = $packer->packMapHeader(\count($value->map));
        foreach ($value->map as $key => $val) {
            $data .= $packer->packStr($key).$packer->pack($val); // keys get packed to str
        }

        return $data;
    }
}

Then register it and wrap your assoc arrays with MessagePack\Type\Map objects:

use MessagePack\Packer;
use MessagePack\Type\Map;

$packer = new Packer();
$packer->registerTransformer(new StringKeyMapTransformer());

$packed = $packer->pack(new Map($data));
fcastilloes commented 6 years ago

Thanks a lot @rybakit, I am busy in other projects now, but this looks great for this and a couple of other types I need to serialize. I'll definitely give it a try.