2017-07-27 1 views
1

protobuf構造の特定のフィールドをマスクする方法が見つかりませんでした。私はFieldMaskUtilについて読んだことがありますが、いくつかの例を試しましたが、逆にFieldMaskに記載されているコピーフィールドが、私が望んでいたものと異なっているようです。サンプル構造と対応するテストコードは次のとおりです。Protobufの特定のフィールドをマスクする方法

プロト:

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; 
    } 

} 

はここでサンプルテストコード

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()); 
} 

}

がここに出力だだ:

私が期待しているだろう何
name: "Harry Alto" 

は、他のすべてのものを印刷しますより私は

私が期待しているだろう何

答えて

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

は、Javadocには、ありませんの名前

以外のすべてのものを印刷することですやりたいする方法はあり

​​

に名前を付けますFieldMaskの場合、振る舞いはあなたの説明と逆です:

フィールドマスクは、get操作によって返される であるか、または更新操作によって変更されるフィールドのサブセットを指定するために使用されます。

マスクは、指定されたフィールドのみを選択して、セット交差操作として機能します。あなたの場合、マスクは「名前」だけを指定するので、それが選択するものです。

あなたが求めている動作は、実際には指定されていないすべてのフィールドを選択した補集合演算です。 Protobuf APIでこれを行う組み込みのメソッドを認識していません。これを実装するためのオプション自身は次のとおりです。

  • は、あなたが保持する各名前付きフィールドのFieldMask#fromStringに別のコールを使用して複数のFieldMaskのインスタンスを構築します。次に、FieldMaskUtil#unionを使用してすべてを結合します。これにより、特にリストされたフィールドだけが保持されます。後でフィールドを追加するためにスキーマを進化させると、それらの新しいフィールドは選択されません。コードを変更して、新しい名前のフィールドをその共用体に追加する必要があります。
  • MessageOrBuilder#getAllFieldsを呼び出して、メッセージ内のすべてのフィールドの記述子を取得します。上記のようにFieldMaskUtil#unionを使用して、すべてを繰り返しますが、無視する特定のフィールド(「名前」など)をスキップします。後でフィールドを追加するためにスキーマを進化させると、新しいフィールドが選択されます。これらの新しいフィールドを含むようにコードを変更する必要はありません。

これらのソリューションのスキーマの進化に関する違いに注意してください。どちらが最適かは、要件によって異なります。

+0

感謝のために@cnaurothに感謝します。提案されたソリューションに感謝します。しようとします。 – Harry

+0

お客様のprotobufをお持ちで、各カスタマーの各protobuf内で名前フィールドをマスクしたい場合はどうなりますか?私は繰り返しフィールドに対処する方法がわかりません。 – junecng

0

あなたが本当にあなたは、このようにそれを行うだろう名前欄消去したい場合:

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

ご希望の結果が得られなければなりません。

関連する問題