如何屏蔽 Protobuf 中的某些字段 [英] How to Mask certain fields in Protobuf

查看:360
本文介绍了如何屏蔽 Protobuf 中的某些字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找不到屏蔽 protobuf 结构中某些字段的方法.我确实阅读了 FieldMaskUtil 并尝试了几个例子,但它似乎做了相反的事情,即复制 FieldMask 中提到的字段,这与我想要的不同.这是示例结构和相应的测试代码.

原型:

syntax = "proto3";包装模型;option java_package = "test.demo.services.protobuf.customer.model";选项 java_outer_classname = "CustomerProto";消息帐户{重复帐户帐户= 1;}消息帐户{int32 id = 1;字符串编号 = 2;int32 customer_id = 3;}留言客户{重复客户客户 = 1;}留言客户{int32 id = 1;字符串比塞尔 = 2;字符串名称 = 3;客户类型类型 = 4;重复帐户帐户= 5;枚举 CustomerType {个人 = 0;公司 = 1;}}

这是示例测试代码

package test.demo.services.protobuf.customer.model;导入 org.junit.Test;导入 test.demo.services.protobuf.customer.model.CustomerProto.Customer;导入 com.google.protobuf.util.FieldMaskUtil;公共类 TestMerge {@测试公共无效擦除字段(){客户请求 = Customer.newBuilder().setId(10).setPesel("12345").setName("Harry Alto").build();//删除名字Customer.Builder modifieldRequest = Customer.newBuilder();FieldMaskUtil.merge(FieldMaskUtil.fromString("name"), request, modifieldRequest);System.out.println( modifieldRequest.build().toString());}

}

输出如下:

name: "Harry Alto"

我所期望的是打印除名称以外的所有内容

id: 10比塞尔:12345"

有没有办法做我想做的事

解决方案

FieldMaskUtil.merge(FieldMaskUtil.fromString("name"), request, modifieldRequest);

<块引用>

我所期望的是打印除名称以外的所有内容

否,根据 JavaDocs for FieldMask,行为与您描述的相反:

<块引用>

字段掩码用于指定字段的子集由获取操作返回或由更新操作修改.

掩码充当集合交集操作,仅选择指定的字段.在您的情况下,掩码仅指定名称",因此这就是它选择的内容.

您正在寻求的行为实际上是一个集合补码操作,选择所有未指定的字段.我不知道 Protobuf API 中的内置方法可以执行此操作.自行实施的选项有:

  • 为要保留的每个命名字段使用对 FieldMask#fromString 的单独调用构造多个 FieldMask 实例.然后,使用 FieldMaskUtil#union 将所有这些组合起来.这将仅保留专门列出的字段.如果您稍后改进架构以添加更多字段,则它不会选择这些新字段.您必须更改代码并将新命名的字段添加到该联合中.
  • 调用MessageOrBuilder#getAllFields 获取消息中所有字段的描述符.如上所述,使用 FieldMaskUtil#union 遍历所有字段,但跳过要忽略的特定字段,例如名称".如果您稍后改进架构以添加更多字段,那么这将选取这些新字段.您无需更改代码即可开始包含这些新字段.

请注意这些解决方案中架构演变方面的差异.选择哪一种最合适取决于您的要求.

I couldnt find a way to mask certain fields in protobuf structure. I did read about the FieldMaskUtil and tried few examples but it seems to do the reverse i.e copy fields which are mentioned in FieldMask which is different from what i wanted. Here's the sample structure and corresponding Test code.

Proto:

syntax = "proto3";

package model;

option java_package = "test.demo.services.protobuf.customer.model";
option java_outer_classname = "CustomerProto";

message Accounts {
  repeated Account account = 1;
}

message Account {

  int32 id = 1;
  string number = 2;
  int32 customer_id = 3;

}

 message Customers {
   repeated Customer customers = 1;
}

message Customer {

  int32 id = 1;
  string pesel = 2;
  string name = 3;
  CustomerType type = 4;
  repeated Account accounts = 5;

  enum CustomerType {
    INDIVIDUAL = 0;
    COMPANY = 1;
  }

}

Here's sample test code

package test.demo.services.protobuf.customer.model;

import org.junit.Test;
import test.demo.services.protobuf.customer.model.CustomerProto.Customer;
import com.google.protobuf.util.FieldMaskUtil;


public class TestMerge {


  @Test
  public void eraseFields() {

        Customer request = Customer.newBuilder().setId(10).setPesel("12345").setName("Harry Alto").build();
    // Erase name
      Customer.Builder modifieldRequest = Customer.newBuilder();
      FieldMaskUtil.merge(FieldMaskUtil.fromString("name"), request, modifieldRequest);
      System.out.println( modifieldRequest.build().toString());
}

}

Here's the output:

name: "Harry Alto"

What i would have expected is to print everything other than name

id: 10
pesel: "12345"

Is there a way to do what i want

解决方案

FieldMaskUtil.merge(FieldMaskUtil.fromString("name"), request, modifieldRequest);

What i would have expected is to print everything other than name

No, according to the JavaDocs for FieldMask, the behavior is opposite of what you described:

Field masks are used to specify a subset of fields that should be returned by a get operation or modified by an update operation.

The mask acts as as a set intersection operation, selecting only fields that were specified. In your case, the mask specifies only "name", so that is what it selects.

The behavior you are seeking is really a set complement operation, selecting all fields that were not specified. I'm not aware of a built-in method in the Protobuf API to do this. Options for implementing this yourself are:

  • Construct multiple FieldMask instances using a separate call to FieldMask#fromString for each named field that you want to retain. Then, use FieldMaskUtil#union to combine all of them. This will retain only the specifically listed fields. If you evolve the schema later to add more fields, then it won't pick up those new fields. You'd have to change the code and add the new named fields into that union.
  • Call MessageOrBuilder#getAllFields to get a descriptor for all fields in the message. Iterate through all of them, using FieldMaskUtil#union as described above, but skip specific fields that you want to ignore, like "name". If you evolve the schema later to add more fields, then this will pick up those new fields. You won't need to change the code to start including those new fields.

Note the differences with respect to schema evolution in those solutions. The choice of which one is most appropriate depends on your requirements.

这篇关于如何屏蔽 Protobuf 中的某些字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆