简体   繁体   English

您如何使用Protostuff序列化Guava的不可变集合?

[英]How do you serialize Guava's immutable collections using Protostuff?

I use protostuff-runtime to serialize object graphs. 我使用protostuff-runtime序列化对象图。 Some of these objects have reference to Guava immutable collections, such as ImmutableList and ImmutableSet. 其中一些对象引用了Guava不可变集合,例如ImmutableList和ImmutableSet。 Protostuff is unable to deserialize these collections out of the box, because it tries to construct an instance and then "add" elements to it from the inputStream (which fails, since the collections are immutable). Protostuff无法立即反序列化这些集合,因为Protostuff尝试构造一个实例,然后从inputStream向其“添加”元素(由于集合是不可变的,因此失败了)。

Do you know of any library / protostuff plugin that does that out of the box? 您知道开箱即用的任何库/原型插件吗? If not, is there a best practice to do this myself? 如果没有,我本人是否有最佳实践?

I've investigated, and found that protostuff has a concept of "delegate" , that lets you take control of the serialization for specific types. 我进行了调查,发现protostuff的概念是“ delegate” ,它使您可以控制特定类型的序列化。 It seems to be the answer to my problem, but I can't seem to get it working. 这似乎是我的问题的答案,但我似乎无法使其正常运行。

Here is what I have right now: 这是我现在所拥有的:

import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;

/**
 * This is the POJO I want to serialize. Note that the {@code strings} field refers to an {@link ImmutableList}.
 */
@Immutable
public class Foo {

    public static final Schema<Foo> SCHEMA = RuntimeSchema.getSchema(Foo.class);

    @Nonnull
    private final ImmutableList<String> strings;

    public Foo(ImmutableList<String> strings) {
        this.strings = Preconditions.checkNotNull(strings);
    }

    @Nonnull
    public ImmutableList<String> getStrings() {
        return strings;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Foo) {
            Foo that = (Foo) obj;
            return this.strings.equals(that.strings);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return strings.hashCode();
    }

}

import com.dyuproject.protostuff.*;
import com.dyuproject.protostuff.runtime.Delegate;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import java.io.IOException;
import java.util.ArrayList;

public class ImmutableListDelegate implements Delegate<ImmutableList<?>> {

    private static final Schema<ArrayList> LIST_SCHEMA = RuntimeSchema.getSchema(ArrayList.class);

    @Override
    public WireFormat.FieldType getFieldType() {
        return WireFormat.FieldType.MESSAGE;
    }

    @Override
    public ImmutableList<?> readFrom(Input input) throws IOException {
        ArrayList<?> list = LIST_SCHEMA.newMessage();
        input.mergeObject(list, LIST_SCHEMA);
        return ImmutableList.copyOf(list);
    }

    @Override
    public void writeTo(Output output, int number, ImmutableList<?> value, boolean repeated) throws IOException {
        ArrayList<?> list = Lists.newArrayList(value);
        output.writeObject(number, list, LIST_SCHEMA, repeated);
        LIST_SCHEMA.writeTo(output, list);
    }

    @Override
    public void transfer(Pipe pipe, Input input, Output output, int number, boolean repeated) throws IOException {
        throw new UnsupportedOperationException("TODO");
    }

    @Override
    public Class<?> typeClass() {
        return ImmutableList.class;
    }
}

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.runtime.DefaultIdStrategy;
import com.dyuproject.protostuff.runtime.RuntimeEnv;
import com.google.common.collect.ImmutableList;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class ImmutableListDelegateTest {

    @Before
    public void before() {
        // registers the delegate
        if (RuntimeEnv.ID_STRATEGY instanceof DefaultIdStrategy) {
            ((DefaultIdStrategy) RuntimeEnv.ID_STRATEGY).registerDelegate(new ImmutableListDelegate());
        }
    }

    @Test
    public void testDelegate() throws IOException {
        Foo foo = new Foo(ImmutableList.of("foo"));

        Assert.assertEquals(foo, serializeThenDeserialize(foo));
    }

    private Foo serializeThenDeserialize(Foo fooToSerialize) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ProtostuffIOUtil.writeDelimitedTo(out, fooToSerialize, Foo.SCHEMA, buffer());
        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        Foo fooDeserialized = Foo.SCHEMA.newMessage();
        ProtostuffIOUtil.mergeDelimitedFrom(in, fooDeserialized, Foo.SCHEMA, buffer());
        return fooDeserialized;
    }

    private LinkedBuffer buffer() {
        return LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
    }
}

The test fails with the following exception, which seems to mean that my delegate only deserializes null values: 测试失败,出现以下异常,这似乎意味着我的委托仅反序列化了空值:

java.lang.NullPointerException
    at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:191)
    at com.google.common.collect.SingletonImmutableList.<init>(SingletonImmutableList.java:40)
    at com.google.common.collect.ImmutableList.asImmutableList(ImmutableList.java:305)
    at com.google.common.collect.ImmutableList.copyFromCollection(ImmutableList.java:314)
    at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:253)
    at test.ImmutableListDelegate.readFrom(ImmutableListDelegate.java:25)
    at test.ImmutableListDelegate.readFrom(ImmutableListDelegate.java:12)
    at com.dyuproject.protostuff.runtime.RuntimeUnsafeFieldFactory$19$1.mergeFrom(RuntimeUnsafeFieldFactory.java:1111)
    at com.dyuproject.protostuff.runtime.MappedSchema.mergeFrom(MappedSchema.java:188)
    at com.dyuproject.protostuff.IOUtil.mergeDelimitedFrom(IOUtil.java:109)
    at com.dyuproject.protostuff.ProtostuffIOUtil.mergeDelimitedFrom(ProtostuffIOUtil.java:151)
    at test.ImmutableListDelegateTest.serializeThenDeserialize(ImmutableListDelegateTest.java:38)
    at test.ImmutableListDelegateTest.testDelegate(ImmutableListDelegateTest.java:30)

Is this the right approach? 这是正确的方法吗? What am I missing? 我想念什么?

This is not a duplicate of the What is a Null Pointer Exception, and how do I fix it? 这不是什么是空指针异常的重复, 我该如何解决? question, which makes no sense. 问题,这没有任何意义。 The fact that I mentioned that an NPE is thrown when trying to use a Protostuff delegate to de-serialize immutable collections, doesn't mean that this duplicates the "What is a NPE?" 我提到在尝试使用Protostuff委托对不可变集合进行反序列化时抛出NPE的事实,并不意味着它重复了“什么是NPE?”。 question in any way, shape, or form. 以任何方式,形状或形式提问。

Everything looks fine and the 一切看起来都很好,

java.lang.NullPointerException
    at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:191)
    at com.google.common.collect.SingletonImmutableList.<init>(SingletonImmutableList.java:40)

says that you're trying to put null into an ImmutableList , which is forbidden. 说您正在尝试将null放入ImmutableList ,这是被禁止的。 To be sure, inspect you list just before the failing line. 可以肯定的是,检查一下您在失败行之前的list Make sure your input json doesn't look like [null] . 确保您输入的json看起来不像[null]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 番石榴一成不变的收藏品的缺陷? - Defects of Immutable collections of Guava? 用于 Guava 不可变集合的 Java 8 收集器? - Java 8 collector for Guava immutable collections? 番石榴不可变集合的序列化是否稳定? - Is the serialization of Guava immutable collections stable? 番石榴不可变集合有用还是只是额外的开销? - Guava immutable collections useful or just extra overhead? 如果您坚持使用 Guava 20.0,如何用替代方法替换 Guava 的 ImmutableSet.toImmutableSet() 收集器? - How to replace Guava's ImmutableSet.toImmutableSet() collector with an alternative, if you're stuck with using Guava 20.0? 我使用Guava的不可变集合(为Java 6编译)和Java 8 JRE,我可以使用新的流接口吗? - I use Guava's immutable collections (compiled for Java 6) and a Java 8 JRE, can I use the new stream interface? 使用 Guava 的不可变类型的防御性副本更简洁的代码? - More succinct code for a defensive copy using Guava's immutable types? 番石榴的ImmutableXXX真的是不变的吗? - Is guava's ImmutableXXX really immutable? guava的ImmutableList并不是真正不可变的 - guava's ImmutableList is not really immutable 如何使用Google Guava创建具有不可变键的Map并且没有重复项? - How to create a Map with immutable keys and no duplicates using Google Guava?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM