1

次の手順でHTTPPOSTリクエストを送受信しています。

FooJson fooJson = new FooJson();
fooJson.setName("Bob");

FooProto.Builder fooProto = FooProto.newBuilder(); // google protobuf
fooProto.setColor("Blue");
fooProto.setLength(30);

BarProto.Builder barProto = BarProto.newBuilder();
barProto.setWeight(65);
fooProto.setBarProto(barProto);

barJson.setFooProto(new String(fooProto.build().toByteArray()));
List<BarJson> barJsonList = new ArrayList<BarJson>();
barJsonList.add(barJson);
fooJson.setBarJsonList(barJsonList);
String data = writeJson(fooJson); // wrapper for jackson JsonGenerator
RequestEntity re = new ByteArrayRequestEntity(data.getBytes());

PostMethod method = new PostMethod("http://foo.net:123/path");
method.setRequestEntity(re);
httpClient.executeMethod(method);

受信側では、次のように解析します。

FooJson fooJson = readJson(request.getInputStream(), FooJson.class);
for (BarJson barJson : fooJson.getBarJsonList()) {
    FooProto fooProto = FooProto.parseFrom(barJson.getFooProto().getBytes());
}

受信側のプロトコルバッファの解析中の結果は次のとおりです。

com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ended unexpectedly in the middle of a field.  This could mean either than the input has been truncated or that an embedded message misreported its own length.

プロトコルバッファを文字列に変換する方法に何か問題がありますか?どうすればこれを修正できますか?

4

2 に答える 2

3

base64やhexエンコーディングなどのエンコードを行わなくても、JSONを介してprotobuf(ペイロードはテキストではなく純粋なバイナリ)を確実にトンネリングできるとは思えません。protobufペイロードをバイトからbase64テキストに変換します。次に、受信側でbase64テキストからバイナリに変換し直します。

受信側のバイト配列が送信したprotobufペイロードと一致しないため、protobuf例外が発生します。ある種のエンコーディングを使用せずに文字列に変換して元に戻すと、データが変更されました。

私はjavax.xml.bind.DatatypeConverterで幸運を祈りました。これはJava1.6の一部です。送信側でprintBase64Binaryを使用し、受信側でparseBase64Binaryを使用します。

[アップデート]

または、base64が醜い場合は、 protobuf-java-formatを使用してprotobufオブジェクトをいくつかの異なる文字列形式(JSON、XML)にシリアル化できます。barJson.setFooProtoにはそれ自体がJSONペイロードである文字列が含まれるため、これは少し奇妙に見えるかもしれません。エスケープされた引用文字はたくさんありますが、機能するはずです。

于 2012-10-10T00:50:42.600 に答える
0

あなたの間違いはここにあります:

barJson.setFooProto(new String(fooProto.build().toByteArray()));

任意のバイナリデータから文字列を作成しようとしないでください。使用中のエンコーディングによっては、データが破損する可能性があります。特にJSONの場合、UTF-8エンコーディングは破損をほぼ保証します(UTF-8では一部のバイトシーケンスが許可されていないため、例外が発生するか、データが変更されます)。

代わりに、フィールドをとして定義しbyte[]、JacksonにBase64エンコーディングを使用させます。これは正しく、比較的効率的に行われます。

最初の回答が示唆しているように、全体にJSONを使用することを検討することもできます。特定のProtobufフレーバーを使用する必要もありません。本当に必要な場合は、いつでもPBオブジェクトを個別に作成できます。

于 2012-10-12T05:54:36.290 に答える