Handling null values in protobuffers

前端 未结 3 622
面向向阳花
面向向阳花 2020-12-13 12:51

I am working on something which fetches data from database and constructs protobuff message. Given the possibility that null values can be fetched from the database for cert

3条回答
  •  不思量自难忘°
    2020-12-13 13:20

    Disclaimer: Answer from a Googler using protobufs on a daily basis. I'm by no means representing Google in any way.

    1. Name your proto Person instead of PersonProto or ProtoPerson. Compiled protobufs are just class definitions specified by the language you are using, with some improvements. Adding "Proto" is extra verbosity.
    2. Use YourMessage.hasYourField() instead of YourMessage.getYourField() != null. Default value for protobuf string is an empty string, which does NOT equal to null. Whereas, no matter whether your field is unset or cleared or empty string, .hasYourField() always returns false. See default values for common protobuf field types.
    3. You've probably known, but I wanna say explicitly: Don't programmatically set a protobuf field to null. Even for outside of protobuf, null causes all sorts of problems. Use .clearYourField() instead.
    4. Person.Builder class does NOT have a .newBuilder() method. Person class does. Understand the Builder Pattern like this: You create a new builder only if you do not have it yet.

    A rewrite of your protobuf:

    message Person {
      optional firstName = 1;
      optional lastName = 2;
      optional address1 = 3;
    }
    

    A rewrite of your logic:

    Person thatPerson = Person.newBuilder()
        .setFirstName("Aaa")
        .setLastName("Bbb")
        .setAddress1("Ccc")
        .build();
    
    Person.Builder thisPersonBuilder = Person.newBuilder()
    
    if (thatPerson.hasFirstName()) {
      thisPersonBuilder.setFirstName(thatPerson.getFirstName());
    }
    
    if (thatPerson.hasLastName()) {
      thisPersonBuilder.setLastName(thatPerson.getLastName());
    }
    
    if (thatPerson.hasAddress1()) {
      thisPersonBuilder.setAddress1(thatPerson.getAddress1());
    }
    
    Person thisPerson = thisPersonBuilder.build();
    

    And if thatPerson is a person object that you created that has attribute values that could be an empty string, empty spaces or null, then I'd recommend using Guava's Strings library:

    import static com.google.common.base.Strings.nullToEmpty;
    
    Person.Builder thisPersonBuilder = Person.newBuilder()
    
    if (!nullToEmpty(thatPerson.getFirstName()).trim().isEmpty()) {
      thisPersonBuilder.setFirstName(thatPerson.getFirstName());
    }
    
    if (!nullToEmpty(thatPerson.hasLastName()).trim().isEmpty()) {
      thisPersonBuilder.setLastName(thatPerson.getLastName());
    }
    
    if (!nullToEmpty(thatPerson.hasAddress1()).trim().isEmpty()) {
      thisPersonBuilder.setAddress1(thatPerson.getAddress1());
    }
    
    Person thisPerson = thisPersonBuilder.build();
    

提交回复
热议问题