簡體   English   中英

如何在Avro中定義LogicalType。 (Java)的

[英]How to define a LogicalType in Avro. (java)

我需要能夠在AVRO模式中標記一些字段,以便在序列化時加密它們。

logicalType允許標記字段,並且與自定義轉換一起允許AVRO透明地加密它們。


我有一些問題需要找到有關如何在AVRO中定義和使用新邏輯類型的文檔( avro_1.8.2#Logical + Types )。
我決定在這里分享我找到的答案,以便讓其他人的生活變得輕松,並在我做錯事情時得到一些反饋。

首先,我將logicalType定義為:

public class EncryptedLogicalType extends LogicalType {
    //The key to use as a reference to the type
    public static final String ENCRYPTED_LOGICAL_TYPE_NAME = "encrypted";

    EncryptedLogicalType() {
        super(ENCRYPTED_LOGICAL_TYPE_NAME);
    }

    @Override
    public void validate(Schema schema) {
        super.validate(schema);
        if (schema.getType() != Schema.Type.BYTES) {
            throw new IllegalArgumentException(
                    "Logical type 'encrypted' must be backed by bytes");
        }
    }
}

然后一個新的轉換:

public class EncryptedConversion extends Conversion<ByteBuffer> {
    // Construct a unique instance for all the conversion. This have to be changed in case the conversion
    //   needs some runtime information (e.g.: an encryption key / a tenant_ID). If so, the get() method should 
    //   return the appropriate conversion per key.
    private static final EncryptedConversion INSTANCE = new EncryptedConversion();
    public static final EncryptedConversion get(){ return INSTANCE; }
    private EncryptedConversion(){ super(); }

    //This conversion operates on ByteBuffer and returns ByteBuffer
    @Override
    public Class<ByteBuffer> getConvertedType() { return ByteBuffer.class; }

    @Override
    public String getLogicalTypeName() { return EncryptedLogicalType.ENCRYPTED_LOGICAL_TYPE_NAME; }

    // fromBytes and toBytes have to be overridden as this conversion works on bytes. Other may need to be 
    //  overridden. The types supported need to be updated also in EncryptedLogicalType#validate(Schema schema)
    @Override
    public ByteBuffer fromBytes(ByteBuffer value, Schema schema, LogicalType type) {
        encryptedValue = __encryptionLogic__(value); 
        return encryptedValue;
    }

    @Override
    public ByteBuffer toBytes(ByteBuffer value, Schema schema, LogicalType type) {
        decryptedValue = __decryptionLogic__(value); 
        return decryptedValue;
    }
}

.avsc模式文件類似於:

{
    "name": “MyMessageWithEncryptedField”,
    "type": "record",
    "fields": [
        {"name": "payload","type" : {"type" : "bytes","logicalType" : "encrypted"}},
        ...

最后在模式文件生成的MyMessageWithEncryptedField.java類中,我添加了返回轉換的方法:

@Override
public Conversion<?> getConversion(int fieldIndex) {
    // This allow us to have a more flexible conversion retrieval, so we don't have to code it per field.
    Schema fieldSchema = SCHEMA$.getFields().get(fieldIndex).schema();
    if ((fieldSchema.getLogicalType() != null)
            && (fieldSchema.getLogicalType().getName() == EncryptedLogicalType.ENCRYPTED_LOGICAL_TYPE_NAME)){
     // here we could pass to the get() method a runtime information, e.g.: a tenantId that can be found in the data structure.
        return EncryptedConversion.get();
    }
    return null;
}

為了讓它運行,我仍然需要在運行時注冊該類型:

LogicalTypes.register(EncryptedLogicalType.ENCRYPTED_LOGICAL_TYPE_NAME, new LogicalTypes.LogicalTypeFactory() {
    private final LogicalType encryptedLogicalType = new EncryptedLogicalType();
    @Override
    public LogicalType fromSchema(Schema schema) {
        return encryptedLogicalType;
    }
});

幾點說明:

  • 如果您的logicalType需要從模式定義傳入的其他屬性,則可以從avro.lang.java.avro.src.main.java.org.apache.avro.LogicalTypes.Decimal中修改LogicalType類。
  • 最后一段代碼(寄存器)當前在我的邏輯開始之前運行,但我計划將它移動到模式生成類( MyMessageWithEncryptedField.java )中的靜態塊中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM