javaprotocol-buffersprotocol-buffers-3

How to Mask certain fields in Protobuf


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


Solution

  • 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:

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