From 3f7628e27495806675ec8c8521e9c33725908936 Mon Sep 17 00:00:00 2001 From: Blake Li Date: Mon, 22 Aug 2022 22:50:31 +0000 Subject: [PATCH] feat: Add numeric enum support. (#1743) Add numeric enum support based on go/actools-numeric-enum-impl. Add a new overloaded toBody method that support serializing request object to Json with numeric enums. --- .../httpjson/ProtoMessageResponseParser.java | 2 +- .../api/gax/httpjson/ProtoRestSerializer.java | 25 ++++++++- .../HttpJsonClientInterceptorTest.java | 2 +- .../httpjson/HttpJsonDirectCallableTest.java | 2 +- ...JsonDirectServerStreamingCallableTest.java | 3 +- .../ProtoMessageRequestFormatterTest.java | 2 +- .../gax/httpjson/ProtoRestSerializerTest.java | 56 +++++++++++++++++-- 7 files changed, 80 insertions(+), 12 deletions(-) diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageResponseParser.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageResponseParser.java index 959efe379..815d19c7a 100644 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageResponseParser.java +++ b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageResponseParser.java @@ -79,7 +79,7 @@ public ResponseT parse(Reader httpContent, TypeRegistry registry) { /* {@inheritDoc} */ @Override public String serialize(ResponseT response) { - return ProtoRestSerializer.create(defaultRegistry).toJson(response); + return ProtoRestSerializer.create(defaultRegistry).toJson(response, false); } // Convert to @AutoValue if this class gets more complicated diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoRestSerializer.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoRestSerializer.java index 9c75be0b0..298a4ce4f 100644 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoRestSerializer.java +++ b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoRestSerializer.java @@ -35,6 +35,7 @@ import com.google.protobuf.Message; import com.google.protobuf.TypeRegistry; import com.google.protobuf.util.JsonFormat; +import com.google.protobuf.util.JsonFormat.Printer; import java.io.IOException; import java.io.Reader; import java.util.List; @@ -69,12 +70,19 @@ static ProtoRestSerializer create(TypeRegis * protobuf native JSON formatter. * * @param message a message to serialize + * @param numericEnum a boolean flag that determine if enum values should be serialized to number + * or not * @throws InvalidProtocolBufferException if failed to serialize the protobuf message to JSON * format */ - String toJson(RequestT message) { + String toJson(RequestT message, boolean numericEnum) { try { - return JsonFormat.printer().usingTypeRegistry(registry).print(message); + Printer printer = JsonFormat.printer().usingTypeRegistry(registry); + if (numericEnum) { + return printer.printingEnumsAsInts().print(message); + } else { + return printer.print(message); + } } catch (InvalidProtocolBufferException e) { throw new RestSerializationException("Failed to serialize message to JSON", e); } @@ -138,6 +146,17 @@ public void putQueryParam(Map> fields, String fieldName, Ob * @param fieldValue a field value to serialize */ public String toBody(String fieldName, RequestT fieldValue) { - return toJson(fieldValue); + return toJson(fieldValue, false); + } + + /** + * Serializes a message to a request body in a form of JSON-encoded string. + * + * @param fieldName a name of a request message field this message belongs to + * @param fieldValue a field value to serialize + * @param numericEnum a boolean flag that determine if enum values should be serialized to number + */ + public String toBody(String fieldName, RequestT fieldValue, boolean numericEnum) { + return toJson(fieldValue, numericEnum); } } diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonClientInterceptorTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonClientInterceptorTest.java index 52c0460b9..8e0a34bb6 100644 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonClientInterceptorTest.java +++ b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonClientInterceptorTest.java @@ -123,7 +123,7 @@ public void onClose(int statusCode, HttpJsonMetadata trailers) { .setRequestBodyExtractor( request -> ProtoRestSerializer.create() - .toBody("*", request.toBuilder().clearName().build())) + .toBody("*", request.toBuilder().clearName().build(), false)) .build()) .setResponseParser( ProtoMessageResponseParser.newBuilder() diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java index ca3e8893e..e47719c5c 100644 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java +++ b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java @@ -83,7 +83,7 @@ public class HttpJsonDirectCallableTest { .setRequestBodyExtractor( request -> ProtoRestSerializer.create() - .toBody("*", request.toBuilder().clearName().build())) + .toBody("*", request.toBuilder().clearName().build(), false)) .build()) .setResponseParser( ProtoMessageResponseParser.newBuilder() diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectServerStreamingCallableTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectServerStreamingCallableTest.java index b929e4dce..fe0240602 100644 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectServerStreamingCallableTest.java +++ b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectServerStreamingCallableTest.java @@ -92,7 +92,8 @@ public class HttpJsonDirectServerStreamingCallableTest { .setRequestBodyExtractor( request -> ProtoRestSerializer.create() - .toBody("*", request.toBuilder().clearBlue().clearRed().build())) + .toBody( + "*", request.toBuilder().clearBlue().clearRed().build(), false)) .build()) .setResponseParser( ProtoMessageResponseParser.newBuilder() diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatterTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatterTest.java index 8a8c0ac66..8f43231c1 100644 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatterTest.java +++ b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatterTest.java @@ -79,7 +79,7 @@ public void setUp() { .setRequestBodyExtractor( request -> { ProtoRestSerializer serializer = ProtoRestSerializer.create(); - return serializer.toBody("field", request); + return serializer.toBody("field", request, false); }) .setAdditionalPaths("/api/v1/names/{name=field_name1/**}/hello") .build(); diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoRestSerializerTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoRestSerializerTest.java index 29d648965..0256f6726 100644 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoRestSerializerTest.java +++ b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoRestSerializerTest.java @@ -48,6 +48,8 @@ public class ProtoRestSerializerTest { private ProtoRestSerializer requestSerializer; private Field field; private String fieldJson; + private String fieldJsonNumericEnum; + private String fieldJsonUnknownNumericEnum; @Before public void setUp() { @@ -72,21 +74,67 @@ public void setUp() { + " \"name\": \"opt_name2\"\n" + " }]\n" + "}"; + + fieldJsonNumericEnum = + "{\n" + + " \"cardinality\": 1,\n" + + " \"number\": 2,\n" + + " \"name\": \"field_name1\",\n" + + " \"options\": [{\n" + + " \"name\": \"opt_name1\"\n" + + " }, {\n" + + " \"name\": \"opt_name2\"\n" + + " }]\n" + + "}"; + + fieldJsonUnknownNumericEnum = + "{\n" + + " \"cardinality\": 7,\n" + + " \"number\": 2,\n" + + " \"name\": \"field_name1\",\n" + + " \"options\": [{\n" + + " \"name\": \"opt_name1\"\n" + + " }, {\n" + + " \"name\": \"opt_name2\"\n" + + " }]\n" + + "}"; } @Test - public void toJson() { - String fieldToJson = requestSerializer.toJson(field); + public void toJson_numericEnumTrue() { + String fieldToJson = requestSerializer.toJson(field, true); + Truth.assertThat(fieldToJson).isEqualTo(fieldJsonNumericEnum); + } + + @Test + public void toJson_numericEnumFalse() { + String fieldToJson = requestSerializer.toJson(field, false); Truth.assertThat(fieldToJson).isEqualTo(fieldJson); } @Test - public void fromJson() { + public void fromJson_numericEnumTrue() { + Field fieldFromJson = + requestSerializer.fromJson(new StringReader(fieldJsonNumericEnum), Field.newBuilder()); + Truth.assertThat(fieldFromJson).isEqualTo(field); + } + + @Test + public void fromJson_numericEnumFalse() { Field fieldFromJson = requestSerializer.fromJson(new StringReader(fieldJson), Field.newBuilder()); Truth.assertThat(fieldFromJson).isEqualTo(field); } + @Test + public void fromJson_numericEnumTrueAndUnknownEnum() { + Field expected = field.toBuilder().setCardinalityValue(7).build(); + Field fieldFromJson = + requestSerializer.fromJson( + new StringReader(fieldJsonUnknownNumericEnum), Field.newBuilder()); + Truth.assertThat(fieldFromJson).isEqualTo(expected); + } + @Test public void fromJsonInvalidJson() { try { @@ -135,7 +183,7 @@ public void putQueryParam() { @Test public void toBody() { - String body = requestSerializer.toBody("bodyField1", field); + String body = requestSerializer.toBody("bodyField1", field, false); Truth.assertThat(body).isEqualTo(fieldJson); } }