public static void deserialize(VersionedObject versionedObject, byte[] data, MutableOffset offset) throws VersionedSerializationException { VersionStack versionStack = null; Map<String, Object> attributes = new HashMap<>(); try { data = CRC.extractDataWithCRC(data, offset); MutableOffset dataOffset = new MutableOffset(); versionStack = new VersionStack((ArrayList<String>) Serializer.deserializeObject(data, dataOffset)); int attributeCount = Serializer.deserializeIntValue(data, dataOffset); for (int i = 0; i < attributeCount; i++) { String attributeName = Serializer.deserializeString(data, dataOffset); String type = Serializer.deserializeString(data, dataOffset); if (type == null) { throw new RuntimeException(); } switch (type) { case "String": attributes.put(attributeName, Serializer.deserializeString(data, dataOffset)); break; case "Boolean": attributes.put(attributeName, Serializer.deserializeBoolean(data, dataOffset)); break; case "Byte": attributes.put(attributeName, Serializer.deserializeByte(data, dataOffset)); break; case "Short": attributes.put(attributeName, Serializer.deserializeShort(data, dataOffset)); break; case "Integer": attributes.put(attributeName, Serializer.deserializeInt(data, dataOffset)); break; case "Long": attributes.put(attributeName, Serializer.deserializeLong(data, dataOffset)); break; case "Float": attributes.put(attributeName, Serializer.deserializeFloat(data, dataOffset)); break; case "Double": attributes.put(attributeName, Serializer.deserializeDouble(data, dataOffset)); break; case "Enum": String enumType = Serializer.deserializeString(data, dataOffset); Class enumClass = Class.forName(enumType); attributes.put(attributeName, Serializer.deserializeEnum(enumClass, data, dataOffset)); break; case "ByteArray": attributes.put(attributeName, Serializer.deserializeBytes(data, dataOffset)); break; case "Serializable": attributes.put(attributeName, Serializer.deserializeObject(data, dataOffset)); break; default: // the VersionedObjectSerializer failed when deserializing the byte array throw new RuntimeException("Unexpected type: " + type); } } versionedObject.deserialize(versionStack.retrieveVersion(), attributes, versionStack); } catch (RuntimeException e) { throw new VersionedSerializationException( versionStack, attributes, VersionedSerializationException.Reason.INCORRECT_DATA); } catch (UnrecognizedVersionException e) { throw new VersionedSerializationException( versionStack, attributes, VersionedSerializationException.Reason.UNRECOGNIZED_VERSION); } catch (ClassNotFoundException e) { throw new VersionedSerializationException( versionStack, attributes, VersionedSerializationException.Reason.CLASS_NOT_FOUND); } catch (CRCMismatchException e) { throw new VersionedSerializationException( null, attributes, VersionedSerializationException.Reason.CRC_MISMATCH); } }