有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java/scala:只对基本类型进行更快的类型感知序列化?

在scala中,我需要序列化仅限于一小部分基本类型的对象:array、list、map、set、int、boolean等。我希望能够以保留序列化格式的类型信息的方式序列化和反序列化这些对象。具体地说,如果我序列化了一个数组[Any],我希望能够对它进行反序列化,并且只指定结果对象是Array[Any]。也就是说,我不想为我要序列化的每一件事情都指定一个结构定义。同时,它需要能够区分int和long、tuple和array等

例如:

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) 个答案

  1. # 1 楼答案

    我不关心库支持的速度或可用性,但您看过ASN.1

  2. # 2 楼答案

    我会使用这样一个简单的界面:

    public interface Serializer{
    
        public <T> T deserialize(String serializedData);
    
        public String serialize(Object data);
    
    }
    

    以及一个enum来实现它:

    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);
    

    (虽然您可以选择不同的序列化格式,但使用枚举策略模式可能仍然是一个好主意)