IonObjectWriter

时间:2020-01-09 10:35:44  来源:igfitidea点击:

" IonObjectWriter"(com.nanosai.gridops.ion.write.IonObjectWriter)可以通过单个方法调用将Java对象写入ION。 " IonObjectWriter"使用Java Reflection检查对象的类并生成相应的ION字段。本教程说明了如何使用IonObjectWriter

使用IonObjectWriter编写Java对象比直接使用IonWriter编写对象要慢,但是这样做要容易得多。我们可以在我们的ION性能基准中看到性能差异。

创建一个IonObjectWriter

创建一个" IonObjectWriter"的过程是这样的:

IonObjectWriter writer = new IonObjectWriter(MyClass.class);

注意" IonObjectWriter"构造函数如何将Java类对象作为参数。创建的" IonObjectWriter"实例只能写入该类的对象。因此,如果需要将不同类的对象写入ION,则需要为要编写其对象的每个类创建一个" IonObjectWriter"。

" IonObjectWriter"构造函数内部发生的操作非常昂贵,因此我们应尽可能重用" IonObjectWriter"实例。

" IonObjectWriter"不是线程安全的,因此我们不应在线程之间共享" IonObjectWriter"实例。仅在同一线程内。

写对象

编写对象是通过使用writeObject()方法完成的。这是一个使用IonObjectWriter`writeObject()方法写入对象的示例:

byte[] dest       = new byte[1024];
int    destOffset = 0;

IonObjectWriter writer = new IonObjectWriter(MyClass.class);
MyClass pojo = new MyClass();

int maxLengthLength = 2;
int bytesWritten = writer.writeObject(pojo, maxLengthLength, dest, destOffset);

该示例首先创建一个"字节"数组,将已序列化的ION数据写入其中,然后将偏移量定义为要从中写入ION数据的"字节"数组。

其次,创建一个" IonObjectWriter",并创建一个POJO实例。

第三,用值2定义" maxLengthLength"变量。该变量定义表示整个序列化ION数据的长度所需的最大字节数。值2表示我们知道ION数据的总序列化大小不会超过65,535字节。数字65,535是可以由2个字节表示的最高数字。 " IonObjectWriter"在内部使用此值来确定为ION Object字段(以及任何其他嵌套的复杂ION字段)保留多少个长度字节。

请注意,尽管ION最多允许15个长度字节,但此处的Java API仅允许最多4个长度字节,因为这是Java字节数组的限制(数组索引为4个字节int)。

最后,POJO通过writeObject()方法被序列化为byte数组。 " writeObject()"将POJO序列化,代表序列化数据长度所需的最大长度长度,目标" byte"数组和该数组中的偏移量作为参数。 writeObject()方法返回写入目标字节数组的字节总数。

IonObjectWriter使用类的字段

" IonObjectWriter"使用Java反射来查看目标类具有哪些字段。这些字段被写入。 " IonObjectWriter"将写入一个类的所有字段,而不管它们是"私有","瞬态"还是其他。" IonObjectWriter"可以并且将访问它们的全部。可以直接访问这些字段。 Getter方法将被忽略。

写入对象的字段时," IonObjectWriter"会将字段名称(变量名称)用作该字段的ION键值。 ION关键字段是ION编码对象属性名称的方式。

如果要从序列中排除字段,或者在序列化的ION数据中为它们使用不同的ION键名,则可以使用IIonObjectWriterConfigurator实例。有关详细信息,请参见下一部分。

配置IonObjectWriter

" IonObjectWriter"具有一个构造函数,该构造函数可以接受一个额外的" IIonObjectWriterConfigurator"实例作为参数。这个IIonObjectWriterConfigurator可以配置IonObjectWriter。

这是用IIonObjectWriterConfigurator接口的匿名实现调用IonObjectWriter构造函数的样子:

IIonObjectWriterConfigurator configurator = new IIonObjectWriterConfigurator() {
    @Override
    public void configure(IonFieldWriterConfiguration config) {

    }
};

IonObjectWriter writer = new IonObjectWriter(MyClass.class, configurator);

IIonObjectWriterConfigurator接口仅包含一个名为configure()的方法。目标类中每个字段每次由IonObjectWriter构造函数调用此方法一次。

configure()方法内部,我们可以设置给定字段的配置。 " IonFieldWriterConfiguration"对象包含单个字段的配置。 " IonFieldWriterConfiguration"对象包含以下字段:

Field   field
String  fieldName
String  alias
boolean include

field和fieldName属性已经填写。field属性包含表示我们可以配置的字段的java.lang.reflect.Field实例。 fieldName包含字段的名称,该名称与我们通过调用field.getName()获得的值相同。

当调用configure()时,alias属性为null。如果我们为" alias"设置了新的String值,则" IonObjectWriter"将在序列化的ION数据中使用该别名,而不是原始字段名称。如果ION数据的读取者期望使用不同的字段名称,或者只是缩短了序列化的ION数据中的字段名称,这将很有用。

调用configure()时,include属性为true,这意味着给定字段将包含在此IonObjectWriter实例编写的ION数据中。如果将include设置为false,则将从该IonObjectWriter写入的ION数据中排除相应的字段。

这是为一个属性设置新别名并排除另一个属性的示例:

IIonObjectWriterConfigurator configurator = new IIonObjectWriterConfigurator() {
    @Override
    public void configure(IonFieldWriterConfiguration config) {
        if("firstName".equals(config.fieldName)) {
            config.alias = "name";
        }
        if("lastName".equals(config.fieldName)) {
            config.include = false;
        }

    }
};

IonObjectWriter writer = new IonObjectWriter(MyClass.class, configurator);