Ich arbeite an etwas, das Daten aus der Datenbank abruft und eine Protobuff-Nachricht erstellt. Angesichts der Möglichkeit, dass für bestimmte Felder Nullwerte aus der Datenbank abgerufen werden können, erhalte ich eine Nullzeiger-Ausnahme, während ich versuche, die protobuff-Nachricht zu erstellen. Erfahren Sie, dass null in Protobuffs aus dem Thread nicht unterstützt wird http://code.google.com/p/protobuf/issues/detail?id=57ich frage mich, ob die einzige andere Möglichkeit, mit dem Auslösen von NPE umzugehen, darin besteht, manuelle Prüfungen in die Java-Datei einzufügen, die dem Proto entspricht, wie unten!
Haftungsausschluss: Antwort von einem Googler, der täglich Protobufs verwendet. Ich vertrete Google in keiner Weise.
Benennen Sie Ihren Prototyp Person Anstatt von PersonProto oder ProtoPerson. Kompilierte Protobufs sind nur Klassendefinitionen, die von der von Ihnen verwendeten Sprache angegeben werden, mit einigen Verbesserungen. Das Hinzufügen von “Proto” ist zusätzliche Ausführlichkeit.
Verwenden YourMessage.hasYourField() Anstatt von YourMessage.getYourField() != null. Der Standardwert für die protobuf-Zeichenfolge ist eine leere Zeichenfolge, was der Fall ist NICHT gleich Null. Unabhängig davon, ob Ihr Feld nicht festgelegt oder gelöscht oder eine leere Zeichenfolge ist, .hasYourField() gibt immer false zurück. Sehen Standardwerte für allgemeine Protobuf-Feldtypen.
Sie haben es wahrscheinlich gewusst, aber ich möchte ausdrücklich sagen: Legen Sie kein protobuf-Feld programmgesteuert fest null. Auch außerhalb von Protobuf, nullverursacht allerlei Probleme. Verwenden .clearYourField() stattdessen.
Person.Builder Klasse tut NICHT haben eine .newBuilder() Methode. Person Klasse tut. Verstehe die Builder-Muster so: Sie erstellen einen neuen Builder nur, wenn Sie ihn noch nicht haben.
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();
Und wenn thatPerson ein von Ihnen erstelltes Personenobjekt mit Attributwerten ist, die eine leere Zeichenfolge, Leerzeichen oder null sein können, dann würde ich die Verwendung empfehlen Guaven Strings Bibliothek:
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();
Ihr Beitrag mag voller guter Ratschläge sein … aber ich bin mir nicht sicher, ob Sie seine Frage verstanden haben? Beispielsweise stammen seine Daten nicht von einem anderen Protobuf-Objekt; Es stammt aus einer Datenbank oder einer anderen Quelle und kann Nullen enthalten. Er wollte im Grunde wissen, wie man mit den Nullen einfach umgeht.
– Erhannis
11. August 2016 um 21:35 Uhr
Guter Punkt Erhannis, danke. Ich habe die Antwort aktualisiert, indem ich einen Abschnitt hinzugefügt habe, der sich mit Objekten ohne Protokollpuffer befasst, die leere Zeichenfolgenwerte, aufeinanderfolgende Leerzeichenwerte und Nullwerte enthalten.
– Michael Xin Sonne
22. September 2017 um 2:08 Uhr
Der Link ‘verursacht alle möglichen Probleme’ ist tot, und ich würde wirklich gerne mehr erfahren
– kinbiko
2. November 2017 um 9:42 Uhr
@kinbiko: Link korrigiert. Guava wurde von Google Code zu GitHub migriert, daher jetzt der neue Link. Danke, dass du mich informiert hast!
– Michael Xin Sonne
2. November 2017 um 18:37 Uhr
Ist diese Antwort nicht genauso wie in der Frage vorgeschlagen – verwenden Sie einfach Nullprüfungen? Der relevante Teil – der Teil, der die Frage beantwortet, befindet sich nur im letzten Absatz. Verwirrenderweise besteht der andere Teil der Antwort darin, Fragen zu beantworten, die nicht gestellt wurden.
Dafür gibt es keine einfache Lösung. Ich würde empfehlen, sich nur mit den Nullprüfungen zu befassen. Aber wenn Sie sie wirklich loswerden wollen, hier sind ein paar Ideen:
Du könntest a schreiben Code-Generator-Plugin was hinzufügt setOrClearFoo() Methoden zu jeder Java-Klasse. Der Java-Code-Generator bietet Einfügepunkte dafür (siehe Ende dieser Seite).
Sie könnten Java-Reflektion verwenden, um über die zu iterieren get*() Methoden von prufen Sie jeden an, suchen Sie nach nullund rufen Sie dann die an set*() Methode von builder wenn nicht null. Dies hat den zusätzlichen Vorteil, dass Sie Ihren Kopiercode nicht jedes Mal aktualisieren müssen, wenn Sie ein neues Feld hinzufügen, aber es ist viel langsamer als das Schreiben von Code, der jedes Feld explizit kopiert.
Bitte werfen Sie einen Blick auf diese Frage stackoverflow.com/questions/21474024/…
– Aarish Ramesh
31. Januar 2014 um 6:45 Uhr
Hat jemand tatsächlich ein Code-Generator-Plugin erstellt, das setOrClearFoo() ausführt oder ein Beispiel liefert?
– Erik Englund
6. Dezember 2018 um 16:51 Uhr
Ich habe Reflektion versucht, aber die Leistung nimmt einen steilen Sprung, wenn der Proto groß wird und Sie den Proto-Objekten einen großen Datensatz zuordnen müssen.
– Dharmvir Tiwari
15. Oktober 2021 um 18:55 Uhr
11451900cookie-checkUmgang mit Nullwerten in Protobuffernyes
Kürzere Version des Gleichen:
Optional.ofNullable(p.getFirstName()).ifPresent(builder::setFirstName);
– Straßenschildkröte
2. Dezember 2016 um 21:20 Uhr
ist der Thread den du verlinkt hast gut? Ich kann dort nichts finden, was mit Nullwerten zu tun hat. Vielleicht hängen diese eher zusammen github.com/protocolbuffers/protobuf/issues/1606 & github.com/protocolbuffers/protobuf/issues/5450
– Seba92
23. Juli 2019 um 8:15 Uhr