Java / Scala: более быстрая сериализация с учетом типов только базовых типов? - PullRequest
0 голосов
/ 27 мая 2011

в Scala, мне нужно сериализовать объекты, которые ограничены небольшим набором базовых типов: массив, список, карта, набор, int, логическое значение и т. Д. Я хочу иметь возможность сериализации и десериализации объектов вспособ, который сохраняет информацию о типе в сериализованном формате.в частности, если я сериализовал Array [Any], я хочу иметь возможность десериализовать его и указать только, что полученным объектом является Array [Any].то есть я не хочу указывать определение структуры для каждой вещи, которую я собираюсь сериализовать.в то же время он должен иметь возможность различать int и long, кортеж и массив и т. д.

, например:

val obj = Array[Any](...) // can have any basic types in here
val ser = serialize(obj)
val newObj = deserialize[Array[Any]](ser) // recovers the exact types from the original obj

json не подходит для этого случая, поскольку он имеетотображение типа "многие к одному" типов scala и типов json.В настоящее время я использую сериализацию Java, но это очень медленно.так как мне не нужно сериализовать произвольный тип объекта, есть ли более быстрая альтернатива для моего более узкого варианта использования?

Ответы [ 2 ]

0 голосов
/ 27 мая 2011

Я бы использовал простой интерфейс, подобный этому:

public interface Serializer{

    public <T> T deserialize(String serializedData);

    public String serialize(Object data);

}

И перечисление для его реализации:

public enum StandardSerializer implements Serializer{
    INTEGER("I", Integer.class, int.class){

        @Override
        protected Integer doDeserialize(final String stripped){
            return Integer.valueOf(stripped);
        }

    },

    STRING("I", String.class){

        @Override
        protected Object doDeserialize(final String stripped){
            return stripped;
        }

    },

    LIST("L", List.class){

        @Override
        protected String doSerialize(final Object data){
            final Iterator<?> it = ((List<?>) ((List<?>) data)).iterator();
            final StringBuilder sb = new StringBuilder();
            if(it.hasNext()){
                Object next = it.next();
                sb.append(StandardSerializer
                    .forType(next.getClass())
                    .serialize(next));
                while(it.hasNext()){
                    sb.append(',');
                    next = it.next();
                    sb.append(StandardSerializer
                        .forType(next.getClass())
                        .serialize(next));
                }
            }

            return sb.toString();
        }

        @Override
        protected Object doDeserialize(final String stripped){
            final List<Object> list = new ArrayList<Object>();
            for(final String item : stripped.split(",")){
                list.add(StandardSerializer.forData(item).deserialize(item));
            }
            return list;
        }
    }

    /* feel free to implement more enum entries */
    ;

    private static final String DELIMITER = ":";

    public static StandardSerializer forType(final Class<?> type){
        for(final StandardSerializer candidate : values()){
            for(final Class<?> supportedType : candidate.supportedClasses){
                if(supportedType.isAssignableFrom(type)) return candidate;
            }
        }
        throw new IllegalArgumentException("Unmapped type: " + type);
    }

    private final String prefix;

    private final Class<?>[] supportedClasses;

    private StandardSerializer(final String prefix,
        final Class<?>... supportedClasses){
        this.prefix = prefix;
        this.supportedClasses = supportedClasses;
    }

    private String base64decode(final String removePrefix){
        // TODO call one of the many base64 libraries here
        return null;
    }

    private String base64encode(final String data){
        // TODO call one of the many base64 libraries here
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public final <T> T deserialize(final String serializedData){
        return (T) doDeserialize(base64decode(removePrefix(serializedData)));
    }

    public static StandardSerializer forData(final String serializedData){
        final String prefix =
            serializedData.substring(0, serializedData.indexOf(DELIMITER));
        for(final StandardSerializer candidate : values()){
            if(candidate.prefix.equals(prefix)) return candidate;
        }
        throw new IllegalArgumentException("Unknown prefix: " + prefix);
    }

    protected abstract Object doDeserialize(String strippedData);

    private String removePrefix(final String serializedData){
        return serializedData.substring(prefix.length() + DELIMITER.length());
    }

    // default implementation calles toString()
    protected String doSerialize(final Object data){
        return data.toString();
    }

    @Override
    public String serialize(final Object data){
        return new StringBuilder()
            .append(prefix)
            .append(DELIMITER)
            .append(base64encode(doSerialize(data)))
            .toString();
    }
}

Теперь вот как вы можете кодировать против этого:

List<?> list = Arrays.asList("abc",123);
String serialized = StandardSerializer.forType(list.getClass()).serialize(list);
List<?> unserialized = StandardSerializer.forData(serialized)
                                         .deserialize(serialized);

(Хотя вы можете выбрать другой формат для сериализации, использование шаблона стратегии enum, вероятно, все еще хорошая идея)

0 голосов
/ 27 мая 2011

Я не думаю о скорости или доступности библиотечной поддержки, но вы смотрели на ASN.1 ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...