Je travaille sur quelque chose qui récupère les données de la base de données et construit un message protobuff. Étant donné la possibilité que des valeurs nulles puissent être extraites de la base de données pour certains champs, j'obtiendrai une exception Null-pointer tout en essayant de construire le message protobuff. Apprendre à savoir que null n'est pas pris en charge dans les protobuffs du fil http://code.google.com/p/protobuf/issues/detail?id=57 , je me demande si la seule autre façon pour gérer le lancement de NPE, c'est insérer des vérifications manuelles dans le fichier Java correspondant au proto comme ci-dessous!
message ProtoPerson{
optional string firstName = 1;
optional string lastName = 2;
optional string address1 = 3;
}
ProtoPerson.Builder builder = ProtoPerson.Builder.newBuilder();
if (p.getFirstName() != null) builder.setFirstName(p.getFirstName());
if (p.getLastName() != null) builder.setLastName(p.getLastName());
if (p.getAddress1() != null) builder.setAddress1(p.getAddress1());
...
Alors, quelqu'un peut-il préciser s'il existe un autre moyen efficace de gérer les valeurs nulles lors de la construction du protobuff ??
Il n'y a pas de solution simple à cela. Je recommanderais simplement de traiter les contrôles nuls. Mais si vous voulez vraiment vous en débarrasser, voici quelques idées:
setOrClearFoo()
à chaque classe Java. Le code Java générateur fournit points d'insertion pour cela (voir la fin de cette page).get*()
de p
, appeler chacune d'elles, rechercher null
, puis appeler la méthode set*()
de builder
si non nulle. Cela aura l'avantage supplémentaire que vous n'aurez pas à mettre à jour votre code de copie chaque fois que vous ajouterez un nouveau champ, mais ce sera beaucoup plus lent que l'écriture de code qui copie explicitement chaque champ.Avertissement: réponse d'un googleur utilisant quotidiennement des protobufs. Je ne représente en aucun cas Google.
Person
au lieu de PersonProto
ou ProtoPerson
. Les protobufs compilés ne sont que des définitions de classe spécifiées par le langage que vous utilisez, avec quelques améliorations. L'ajout de "Proto" est une verbosité supplémentaire.YourMessage.hasYourField()
au lieu de YourMessage.getYourField() != null
. La valeur par défaut de la chaîne de protobuf est une chaîne vide, qui [~ # ~] n'est pas [~ # ~] égale à null. Alors que votre champ est non défini ou effacé ou vide, .hasYourField()
retourne toujours false. Voir valeurs par défaut pour les types de champs protobuf courants .null
. Même pour l'extérieur de protobuf, null
cause toutes sortes de problèmes . Utilisez à la place .clearYourField()
.Person.Builder
A [~ # ~] pas [~ # ~] une méthode .newBuilder()
. Person
classe le fait. Comprenez le Modèle de générateur comme ceci: vous créez un nouveau générateur uniquement si vous ne l'avez pas encore.Une réécriture de votre protobuf:
message Person {
optional firstName = 1;
optional lastName = 2;
optional address1 = 3;
}
Une réécriture de votre logique:
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();
Et si thatPerson
est un objet personne que vous avez créé et qui a des valeurs d'attribut qui pourraient être une chaîne vide, des espaces vides ou null, alors je recommanderais d'utiliser la bibliothèque Strings
de Guava :
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();