gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 08:04:06 26 4
gpt4 key购买 nike

我使用 protostuff-runtime 来序列化对象图。其中一些对象引用了 Guava 不可变集合,例如 ImmutableList 和 ImmutableSet。 Protostuff 无法开箱即用地反序列化这些集合,因为它尝试构造一个实例,然后从 inputStream 向其“添加”元素(这会失败,因为集合是不可变的)。

您知道有任何库/原型(prototype)插件可以开箱即用吗?如果没有,是否有自己执行此操作的最佳实践?

我调查过,发现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);
}
}

测试失败并出现以下异常,这似乎意味着我的委托(delegate)仅反序列化空值:

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)

这是正确的方法吗?我错过了什么?

这不是 What is a Null Pointer Exception, and how do I fix it? 的重复项问题,这毫无意义。我提到在尝试使用 Protostuff 委托(delegate)来反序列化不可变集合时会抛出 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]

关于java - 如何使用 Protostuff 序列化 Guava 的不可变集合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12352559/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com