[英]How do you serialize Guava's immutable collections using Protostuff?
我使用protostuff-runtime序列化對象圖。 其中一些對象引用了Guava不可變集合,例如ImmutableList和ImmutableSet。 Protostuff無法立即反序列化這些集合,因為Protostuff嘗試構造一個實例,然后從inputStream向其“添加”元素(由於集合是不可變的,因此失敗了)。
您知道開箱即用的任何庫/原型插件嗎? 如果沒有,我本人是否有最佳實踐?
我進行了調查,發現protostuff的概念是“ delegate” ,它使您可以控制特定類型的序列化。 這似乎是我的問題的答案,但我似乎無法使其正常運行。
這是我現在所擁有的:
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);
}
}
測試失敗,出現以下異常,這似乎意味着我的委托僅反序列化了空值:
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)
這是正確的方法嗎? 我想念什么?
這不是什么是空指針異常的重復, 我該如何解決? 問題,這沒有任何意義。 我提到在嘗試使用Protostuff委托對不可變集合進行反序列化時拋出NPE的事實,並不意味着它重復了“什么是NPE?”。 以任何方式,形狀或形式提問。
一切看起來都很好,
java.lang.NullPointerException
at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:191)
at com.google.common.collect.SingletonImmutableList.<init>(SingletonImmutableList.java:40)
說您正在嘗試將null
放入ImmutableList
,這是被禁止的。 可以肯定的是,檢查一下您在失敗行之前的list
。 確保您輸入的json看起來不像[null]
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.