METHOD_SAY_HELLO =
GreeterGrpc.getSayHelloMethod()
.toBuilder(
- ProtoUtils.jsonMarshaller(HelloRequest.getDefaultInstance()),
- ProtoUtils.jsonMarshaller(HelloReply.getDefaultInstance()))
+ JsonMarshaller.jsonMarshaller(HelloRequest.getDefaultInstance()),
+ JsonMarshaller.jsonMarshaller(HelloReply.getDefaultInstance()))
.build();
protected HelloJsonStub(Channel channel) {
diff --git a/examples/src/main/java/io/grpc/examples/advanced/JsonMarshaller.java b/examples/src/main/java/io/grpc/examples/advanced/JsonMarshaller.java
new file mode 100644
index 0000000000..7b9aae94f8
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/advanced/JsonMarshaller.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018 The gRPC Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.grpc.examples.advanced;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.Message;
+import com.google.protobuf.Message.Builder;
+import com.google.protobuf.util.JsonFormat;
+import com.google.protobuf.util.JsonFormat.Parser;
+import com.google.protobuf.util.JsonFormat.Printer;
+import io.grpc.ExperimentalApi;
+import io.grpc.MethodDescriptor.Marshaller;
+import io.grpc.Status;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+
+/**
+ * A {@link Marshaller} for JSON. This marshals in the Protobuf 3 format described here:
+ * https://developers.google.com/protocol-buffers/docs/proto3#json
+ */
+final class JsonMarshaller {
+
+ private JsonMarshaller() {}
+
+ /**
+ * Create a {@code Marshaller} for json protos of the same type as {@code defaultInstance}.
+ *
+ * This is an unstable API and has not been optimized yet for performance.
+ */
+ public static Marshaller jsonMarshaller(final T defaultInstance) {
+ final Parser parser = JsonFormat.parser();
+ final Printer printer = JsonFormat.printer();
+ return jsonMarshaller(defaultInstance, parser, printer);
+ }
+
+ /**
+ * Create a {@code Marshaller} for json protos of the same type as {@code defaultInstance}.
+ *
+ * This is an unstable API and has not been optimized yet for performance.
+ */
+ public static Marshaller jsonMarshaller(
+ final T defaultInstance, final Parser parser, final Printer printer) {
+
+ final Charset charset = Charset.forName("UTF-8");
+
+ return new Marshaller() {
+ @Override
+ public InputStream stream(T value) {
+ try {
+ return new ByteArrayInputStream(printer.print(value).getBytes(charset));
+ } catch (InvalidProtocolBufferException e) {
+ throw Status.INTERNAL
+ .withCause(e)
+ .withDescription("Unable to print json proto")
+ .asRuntimeException();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T parse(InputStream stream) {
+ Builder builder = defaultInstance.newBuilderForType();
+ Reader reader = new InputStreamReader(stream, charset);
+ T proto;
+ try {
+ parser.merge(reader, builder);
+ proto = (T) builder.build();
+ reader.close();
+ } catch (InvalidProtocolBufferException e) {
+ throw Status.INTERNAL.withDescription("Invalid protobuf byte sequence")
+ .withCause(e).asRuntimeException();
+ } catch (IOException e) {
+ // Same for now, might be unavailable
+ throw Status.INTERNAL.withDescription("Invalid protobuf byte sequence")
+ .withCause(e).asRuntimeException();
+ }
+ return proto;
+ }
+ };
+ }
+}
diff --git a/grpclb/build.gradle b/grpclb/build.gradle
index 95ca0a6e0a..63381e9589 100644
--- a/grpclb/build.gradle
+++ b/grpclb/build.gradle
@@ -17,6 +17,10 @@ dependencies {
project(':grpc-protobuf'),
project(':grpc-stub'),
libraries.protobuf
+ compile (libraries.protobuf_util) {
+ // prefer 20.0 from libraries instead of 19.0
+ exclude group: 'com.google.guava', module: 'guava'
+ }
compileOnly libraries.javax_annotation
testCompile libraries.truth,
project(':grpc-core').sourceSets.test.output
diff --git a/protobuf/build.gradle b/protobuf/build.gradle
index 74bea7fb34..fb2e14c484 100644
--- a/protobuf/build.gradle
+++ b/protobuf/build.gradle
@@ -17,11 +17,6 @@ dependencies {
libraries.protobuf,
libraries.guava
- compile (libraries.protobuf_util) {
- // prefer 20.0 from libraries instead of 19.0
- exclude group: 'com.google.guava', module: 'guava'
- }
-
compile (libraries.google_api_protos) {
// 'com.google.api:api-common' transitively depends on auto-value, which breaks our
// annotations.
diff --git a/protobuf/src/main/java/io/grpc/protobuf/ProtoUtils.java b/protobuf/src/main/java/io/grpc/protobuf/ProtoUtils.java
index c1ac29a352..00421de102 100644
--- a/protobuf/src/main/java/io/grpc/protobuf/ProtoUtils.java
+++ b/protobuf/src/main/java/io/grpc/protobuf/ProtoUtils.java
@@ -16,23 +16,10 @@
package io.grpc.protobuf;
-import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
-import com.google.protobuf.Message.Builder;
-import com.google.protobuf.util.JsonFormat;
-import com.google.protobuf.util.JsonFormat.Parser;
-import com.google.protobuf.util.JsonFormat.Printer;
-import io.grpc.ExperimentalApi;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor.Marshaller;
-import io.grpc.Status;
import io.grpc.protobuf.lite.ProtoLiteUtils;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.Charset;
/**
* Utility methods for using protobuf with grpc.
@@ -44,65 +31,6 @@ public class ProtoUtils {
return ProtoLiteUtils.marshaller(defaultInstance);
}
- /**
- * Create a {@code Marshaller} for json protos of the same type as {@code defaultInstance}.
- *
- * This is an unstable API and has not been optimized yet for performance.
- */
- @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1786")
- public static Marshaller jsonMarshaller(final T defaultInstance) {
- final Parser parser = JsonFormat.parser();
- final Printer printer = JsonFormat.printer();
- return jsonMarshaller(defaultInstance, parser, printer);
- }
-
- /**
- * Create a {@code Marshaller} for json protos of the same type as {@code defaultInstance}.
- *
- * This is an unstable API and has not been optimized yet for performance.
- */
- @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1786")
- public static Marshaller jsonMarshaller(
- final T defaultInstance, final Parser parser, final Printer printer) {
-
- final Charset charset = Charset.forName("UTF-8");
-
- return new Marshaller() {
- @Override
- public InputStream stream(T value) {
- try {
- return new ByteArrayInputStream(printer.print(value).getBytes(charset));
- } catch (InvalidProtocolBufferException e) {
- throw Status.INTERNAL
- .withCause(e)
- .withDescription("Unable to print json proto")
- .asRuntimeException();
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public T parse(InputStream stream) {
- Builder builder = defaultInstance.newBuilderForType();
- Reader reader = new InputStreamReader(stream, charset);
- T proto;
- try {
- parser.merge(reader, builder);
- proto = (T) builder.build();
- reader.close();
- } catch (InvalidProtocolBufferException e) {
- throw Status.INTERNAL.withDescription("Invalid protobuf byte sequence")
- .withCause(e).asRuntimeException();
- } catch (IOException e) {
- // Same for now, might be unavailable
- throw Status.INTERNAL.withDescription("Invalid protobuf byte sequence")
- .withCause(e).asRuntimeException();
- }
- return proto;
- }
- };
- }
-
/**
* Produce a metadata key for a generated protobuf type.
*/
diff --git a/protobuf/src/test/java/io/grpc/protobuf/ProtoUtilsTest.java b/protobuf/src/test/java/io/grpc/protobuf/ProtoUtilsTest.java
index 20da6a0129..74707c9103 100644
--- a/protobuf/src/test/java/io/grpc/protobuf/ProtoUtilsTest.java
+++ b/protobuf/src/test/java/io/grpc/protobuf/ProtoUtilsTest.java
@@ -17,20 +17,12 @@
package io.grpc.protobuf;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
import com.google.common.io.ByteStreams;
-import com.google.protobuf.Any;
-import com.google.protobuf.ByteString;
import com.google.protobuf.Type;
import io.grpc.MethodDescriptor.Marshaller;
-import io.grpc.Status;
-import io.grpc.StatusRuntimeException;
import java.io.ByteArrayInputStream;
-import java.io.IOException;
import java.io.InputStream;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -53,77 +45,4 @@ public class ProtoUtilsTest {
assertEquals("google.protobuf.Type-bin",
ProtoUtils.keyForProto(Type.getDefaultInstance()).originalName());
}
-
- @Test
- public void testJsonRoundtrip() throws Exception {
- Marshaller marshaller = ProtoUtils.jsonMarshaller(Type.getDefaultInstance());
- InputStream is = marshaller.stream(proto);
- is = new ByteArrayInputStream(ByteStreams.toByteArray(is));
- assertEquals(proto, marshaller.parse(is));
- }
-
- @Test
- public void testJsonMarshallerFailToPrint() {
- Marshaller marshaller = ProtoUtils.jsonMarshaller(Any.getDefaultInstance());
- try {
- marshaller.stream(
- Any.newBuilder().setValue(ByteString.copyFromUtf8("invalid (no type url)")).build());
- fail("Expected exception");
- } catch (StatusRuntimeException e) {
- assertNotNull(e.getCause());
- assertNotNull(e.getMessage());
- assertEquals(Status.Code.INTERNAL, e.getStatus().getCode());
- }
- }
-
- @Test
- public void testJsonRepresentation() throws Exception {
- Marshaller marshaller = ProtoUtils.jsonMarshaller(Type.getDefaultInstance());
- InputStream is = marshaller.stream(proto);
- String s = new String(ByteStreams.toByteArray(is), "UTF-8");
- assertEquals("{\"name\":\"value\"}", s.replaceAll("\\s", ""));
- }
-
- @Ignore("https://github.com/google/protobuf/issues/1470")
- @Test
- public void testJsonInvalid() throws Exception {
- Marshaller marshaller = ProtoUtils.jsonMarshaller(Type.getDefaultInstance());
- try {
- marshaller.parse(new ByteArrayInputStream("{]".getBytes("UTF-8")));
- fail("Expected exception");
- } catch (StatusRuntimeException ex) {
- assertEquals(Status.Code.INTERNAL, ex.getStatus().getCode());
- assertNotNull(ex.getCause());
- }
- }
-
- @Test
- public void testJsonInvalidProto() throws Exception {
- Marshaller marshaller = ProtoUtils.jsonMarshaller(Type.getDefaultInstance());
- try {
- marshaller.parse(new ByteArrayInputStream("{\"\":3}".getBytes("UTF-8")));
- fail("Expected exception");
- } catch (StatusRuntimeException ex) {
- assertEquals(Status.Code.INTERNAL, ex.getStatus().getCode());
- assertNotNull(ex.getCause());
- }
- }
-
- @Test
- public void testJsonIoException() throws Exception {
- Marshaller marshaller = ProtoUtils.jsonMarshaller(Type.getDefaultInstance());
- final IOException ioe = new IOException();
- try {
- marshaller.parse(new ByteArrayInputStream("{}".getBytes("UTF-8")) {
- @Override
- public void close() throws IOException {
- throw ioe;
- }
- });
- fail("Exception expected");
- } catch (StatusRuntimeException ex) {
- assertEquals(Status.Code.INTERNAL, ex.getStatus().getCode());
- assertEquals(ioe, ex.getCause());
- }
- }
}
diff --git a/services/build.gradle b/services/build.gradle
index 3a2b52a57c..f9c34337d6 100644
--- a/services/build.gradle
+++ b/services/build.gradle
@@ -16,6 +16,11 @@ description = "gRPC: Services"
dependencies {
compile project(':grpc-protobuf'),
project(':grpc-stub')
+ compile (libraries.protobuf_util) {
+ // prefer 20.0 from libraries instead of 19.0
+ exclude group: 'com.google.guava', module: 'guava'
+ }
+
compileOnly libraries.javax_annotation
testCompile project(':grpc-testing'),
libraries.netty_epoll // for DomainSocketAddress