Ответ 1
Хорошо, я просто потратил два часа или около того, изучая это, что намного больше, чем я планирую потратить на это. Но я был заинтригован.
Я думаю, что вы, возможно, обнаружили законную ошибку в кодировке AMF ActionScript (или в том, как класс Dictionary
получает Seralized через AMF). Ошибка влияет на все, что использует AMF, поэтому такая же ошибка воспроизводится с помощью ByteArray
, поэтому я собираюсь использовать ее для демонстрационных целей.
Рассмотрим следующий код:
var d:Dictionary = new Dictionary(false);
d["goodbye"] = "world";
d["hello"] = "world";
delete d["hello"]
var ba:ByteArray = new ByteArray();
ba.writeObject(d);
var len:uint = ba.position;
ba.position = 0;
for(var i:uint=0;i<len;i++) {
trace(ba.readUnsignedByte().toString(16));
}
Выход будет:
11 05 00 06 0f 67 6f 6f 64 62 79 65 06 0b 77 6f 72 6c 64
Теперь, если мы никогда не ставим "hello"
в качестве ключа:
var d:Dictionary = new Dictionary(false);
d["goodbye"] = "world";
var ba:ByteArray = new ByteArray();
ba.writeObject(d);
var len:uint = ba.position;
ba.position = 0;
for(var i:uint=0;i<len;i++) {
trace(ba.readUnsignedByte().toString(16));
}
Вывод:
11 03 00 06 0f 67 6f 6f 64 62 79 65 06 0b 77 6f 72 6c 64
Обратите внимание, что длина точно такая же, однако они отличаются во втором байте.
Теперь посмотрим на сериализацию, если я не удаляю "hello"
:
11 05 01 06 0b 68 65 6c 6c 6f 06 0b 77 6f 72 6c 64 06 0f 67 6f 6f 64 62 79 65 06 02
Обратите внимание, что 05
во втором байте совпадает с тем, как мы его удалили. Я думаю, что это указывает количество предметов в словаре. Я говорю "я думаю", потому что я долгое время проделывал документацию на AMF0/3, пытаясь выяснить, что именно происходит здесь, потому что это не похоже на сериализацию словаря, но его довольно последовательная, но я этого не понимаю.
Итак, я думаю, почему вы делаете исключение (в частности, ошибку "Конец файла" ), потому что он все еще считает, что в словаре должен быть другой элемент, который должен быть де-сериализован.
Ваш альтернативный метод работает, потому что вы строите новый словарь и заполняете его... Его "внутренний счетчик" только увеличивается, поэтому он работает как шарм.
Еще одно замечание: если вы установите d["Hello"] = undefined
, он не генерирует исключение, но элемент не будет удален из словаря. Ключ становится сериализованным со значением undefined
в потоке AMF. Таким образом, полученный байт-поток длиннее, чем если бы он никогда не был там.
Использование Object
, похоже, не демонстрирует такого же поведения. Это не только не приводит к ошибке, созданный байт-код в большей степени соответствует документации AMF0/3, которую я могу найти у Adobe. И полученный "ключ" буквально отбрасывается из сериализации, как будто этого на самом деле никогда не было. Поэтому я не уверен, какой особый случай они используют для Dictionary
(видимо, недокументированный тип данных AMF3 0x11
), но он не воспроизводится правильно с удалением элементов из него.
Мне кажется, что это законная ошибка.
изменить
Итак, я немного потянулся и нашел других людей, говорящих о AMF-серилизации Dictionary
.
0x11 : Dictionary Data Type
0x05 : Bit code: XXXX XXXY
: If y == 0 then X is a reference to a previously encoded object in the stream
: If y == 1 then X is the number of key/val pairs in the dictionary.
Итак, если этот случай 5&1 == 1
и 5>>1 == 2
, поэтому он ожидает две пары ключ/вал в "плохой" сериализованной версии.