Repository: googleapis/google-api-java-client
Pull request #1831 (2021-06-18 20:55:11)

fix: add reason field to Details in GoogleJsonErrorObject
Fixes b/191502543

google-api-java-client id parsing error objects without `reason` field in `details`.
The actual error message:
```
{
  "error": {
    "code": 400,
    "message": "The subscription is in a state that is not valid for the requested operation",
    "status": "FAILED_PRECONDITION",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "ERROR_CODE_SUBSCRIPTION_BAD_STATE"
      }
    ]
  }
}
```
But when it get parsed through java api-client, it becomes:
```
{
  "code" : 400,
  "details" : [ {
    "@type" : "type.googleapis.com/google.rpc.ErrorInfo"
  } ],
  "message" : "The subscription is in a state that is not valid for the requested operation",
  "status" : "FAILED_PRECONDITION"
}
```


Patch:
diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/json/GoogleJsonError.java b/google-api-client/src/main/java/com/google/api/client/googleapis/json/GoogleJsonError.java
index 1a530145..246c3fd1 100644
--- a/google-api-client/src/main/java/com/google/api/client/googleapis/json/GoogleJsonError.java
+++ b/google-api-client/src/main/java/com/google/api/client/googleapis/json/GoogleJsonError.java
@@ -189,6 +189,7 @@ public class GoogleJsonError extends GenericJson {
     private String type;
 
     @Key private String detail;
+    @Key private String reason;
     @Key private List<ParameterViolations> parameterViolations;
 
     public String getType() {
@@ -207,6 +208,14 @@ public class GoogleJsonError extends GenericJson {
       this.detail = detail;
     }
 
+    public String getReason() {
+      return reason;
+    }
+
+    public void setReason(String reason) {
+      this.reason = reason;
+    }
+
     public List<ParameterViolations> getParameterViolations() {
       return parameterViolations;
     }
diff --git a/pom.xml b/pom.xml
index ebc61ac0..5e120151 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
   <packaging>pom</packaging>
   <name>Parent for the Google API Client Library for Java</name>
   <description>The Google APIs Client Library for Java is a Java client library
-               for accessing any HTTP-based API on the web</description>
+    for accessing any HTTP-based API on the web</description>
   <url>https://github.com/googleapis/google-api-java-client</url>
 
   <issueManagement>
@@ -17,7 +17,7 @@
   </issueManagement>
 
   <inceptionYear>2010</inceptionYear>
-  
+
   <developers>
     <developer>
       <id>chingor</id>


Test patch:
diff --git a/google-api-client/src/test/java/com/google/api/client/googleapis/json/GoogleJsonErrorTest.java b/google-api-client/src/test/java/com/google/api/client/googleapis/json/GoogleJsonErrorTest.java
index 99cc3b1d..c988804a 100644
--- a/google-api-client/src/test/java/com/google/api/client/googleapis/json/GoogleJsonErrorTest.java
+++ b/google-api-client/src/test/java/com/google/api/client/googleapis/json/GoogleJsonErrorTest.java
@@ -125,4 +125,48 @@ public class GoogleJsonErrorTest extends TestCase {
     assertEquals(DETAILS_ERROR, FACTORY.toString(errorResponse));
     assertNotNull(errorResponse.getDetails());
   }
+
+  public void testParse_withReasonInDetails() throws Exception {
+    String DETAILS_ERROR =
+        "{"
+            + "\"code\":400,"
+            + "\"details\":"
+            + "[{"
+            + "\"@type\":\"type.googleapis.com/google.dataflow.v1beta3.InvalidTemplateParameters\","
+            + "\"parameterViolations\":[{"
+            + "\"description\":\"Parameter didn't match regex '^[0-9a-zA-Z_]+$'\","
+            + "\"parameter\":\"safeBrowsingApiKey\""
+            + "}],"
+            + "\"reason\":\"TEST REASON 1\""
+            + "},{"
+            + "\"@type\":\"type.googleapis.com/google.rpc.DebugInfo\","
+            + "\"detail\":\"test detail\""
+            + "},{"
+            + "\"@type\":\"type.googleapis.com/google.rpc.DebugInfo\","
+            + "\"reason\":\"test reason 2\""
+            + "},{"
+            + "\"@type\":\"type.googleapis.com/google.rpc.DebugInfo\""
+            + "}],"
+            + "\"message\":\"The template parameters are invalid.\","
+            + "\"status\":\"INVALID_ARGUMENT\""
+            + "}";
+    InputStream errorContent =
+        GoogleJsonErrorTest.class.getResourceAsStream("errorWithReasonInDetails.json");
+
+    HttpTransport transport =
+        new ErrorTransport(
+            new MockLowLevelHttpResponse()
+                .setContent(errorContent)
+                .setContentType(Json.MEDIA_TYPE)
+                .setStatusCode(HttpStatusCodes.STATUS_CODE_FORBIDDEN));
+    HttpRequest request =
+        transport.createRequestFactory().buildGetRequest(HttpTesting.SIMPLE_GENERIC_URL);
+    request.setThrowExceptionOnExecuteError(false);
+    HttpResponse response = request.execute();
+    com.google.api.client.googleapis.json.GoogleJsonError errorResponse =
+        com.google.api.client.googleapis.json.GoogleJsonError.parse(FACTORY, response);
+
+    assertEquals(DETAILS_ERROR, FACTORY.toString(errorResponse));
+    assertNotNull(errorResponse.getDetails().get(2).getReason());
+  }
 }
diff --git a/google-api-client/src/test/resources/com/google/api/client/googleapis/json/errorWithReasonInDetails.json b/google-api-client/src/test/resources/com/google/api/client/googleapis/json/errorWithReasonInDetails.json
new file mode 100644
index 00000000..cd1b85ad
--- /dev/null
+++ b/google-api-client/src/test/resources/com/google/api/client/googleapis/json/errorWithReasonInDetails.json
@@ -0,0 +1,31 @@
+{
+  "error": {
+    "code": 400,
+    "message": "The template parameters are invalid.",
+    "status": "INVALID_ARGUMENT",
+    "details": [
+      {
+        "@type": "type.googleapis.com/google.dataflow.v1beta3.InvalidTemplateParameters",
+        "reason": "TEST REASON 1",
+        "parameterViolations": [
+          {
+            "parameter": "safeBrowsingApiKey",
+            "description": "Parameter didn't match regex '^[0-9a-zA-Z_]+$'"
+          }
+        ]
+      },
+      {
+        "@type": "type.googleapis.com/google.rpc.DebugInfo",
+        "detail": "test detail"
+      },
+      {
+        "@type": "type.googleapis.com/google.rpc.DebugInfo",
+        "reason": "test reason 2"
+      },
+      {
+        "@type": "type.googleapis.com/google.rpc.DebugInfo"
+      }
+    ]
+  }
+}
+