0
# JSON Error Handling
1
2
Structured JSON error response parsing and exception handling with detailed error information from Google API responses.
3
4
## Core Imports
5
6
```java
7
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
8
import com.google.api.client.googleapis.json.GoogleJsonError;
9
import com.google.api.client.googleapis.json.GoogleJsonErrorContainer;
10
import com.google.api.client.json.JsonFactory;
11
```
12
13
## Exception Classes
14
15
### GoogleJsonResponseException
16
17
HTTP response exception that includes structured JSON error details from Google APIs.
18
19
```java { .api }
20
public class GoogleJsonResponseException extends HttpResponseException {
21
public GoogleJsonError getDetails();
22
23
public static GoogleJsonResponseException from(JsonFactory jsonFactory, HttpResponse response)
24
throws IOException;
25
26
protected GoogleJsonResponseException(Builder builder, GoogleJsonError details);
27
28
public static class Builder extends HttpResponseException.Builder {
29
public GoogleJsonResponseException build();
30
public Builder setDetails(GoogleJsonError details);
31
public GoogleJsonError getDetails();
32
}
33
}
34
```
35
36
**Usage Example:**
37
38
```java
39
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
40
import com.google.api.client.googleapis.json.GoogleJsonError;
41
42
try {
43
// Execute Google API request
44
MyApiResponse response = myApiClient.items().get(itemId).execute();
45
} catch (GoogleJsonResponseException e) {
46
// Handle structured JSON error
47
GoogleJsonError error = e.getDetails();
48
49
System.err.println("API Error: " + e.getStatusCode() + " " + e.getStatusMessage());
50
51
if (error != null) {
52
System.err.println("Error Code: " + error.getCode());
53
System.err.println("Error Message: " + error.getMessage());
54
55
// Handle specific error cases
56
switch (e.getStatusCode()) {
57
case 400:
58
handleBadRequest(error);
59
break;
60
case 401:
61
handleUnauthorized(error);
62
break;
63
case 403:
64
handleForbidden(error);
65
break;
66
case 404:
67
handleNotFound(error);
68
break;
69
case 429:
70
handleRateLimitExceeded(error);
71
break;
72
case 500:
73
handleInternalServerError(error);
74
break;
75
default:
76
handleGenericError(error);
77
}
78
}
79
} catch (IOException e) {
80
// Handle general I/O errors
81
System.err.println("Network error: " + e.getMessage());
82
}
83
```
84
85
## Error Detail Classes
86
87
### GoogleJsonError
88
89
Represents detailed error information from Google JSON API responses.
90
91
```java { .api }
92
public final class GoogleJsonError extends GenericJson {
93
public Integer getCode();
94
public GoogleJsonError setCode(Integer code);
95
96
public String getMessage();
97
public GoogleJsonError setMessage(String message);
98
99
public List<ErrorInfo> getErrors();
100
public GoogleJsonError setErrors(List<ErrorInfo> errors);
101
102
public static final class ErrorInfo extends GenericJson {
103
public String getDomain();
104
public ErrorInfo setDomain(String domain);
105
106
public String getReason();
107
public ErrorInfo setReason(String reason);
108
109
public String getMessage();
110
public ErrorInfo setMessage(String message);
111
112
public String getLocation();
113
public ErrorInfo setLocation(String location);
114
115
public String getLocationType();
116
public ErrorInfo setLocationType(String locationType);
117
118
public String getExtendedHelp();
119
public ErrorInfo setExtendedHelp(String extendedHelp);
120
121
public String getSendReport();
122
public ErrorInfo setSendReport(String sendReport);
123
}
124
}
125
```
126
127
### GoogleJsonErrorContainer
128
129
Container for Google JSON errors, used in batch operations and some API responses.
130
131
```java { .api }
132
public class GoogleJsonErrorContainer extends GenericJson {
133
public GoogleJsonError getError();
134
public GoogleJsonErrorContainer setError(GoogleJsonError error);
135
}
136
```
137
138
**Usage Example:**
139
140
```java
141
import com.google.api.client.googleapis.json.GoogleJsonError;
142
143
// Detailed error handling
144
private void handleDetailedError(GoogleJsonError error) {
145
System.err.println("Main Error: " + error.getCode() + " - " + error.getMessage());
146
147
// Process individual error details
148
if (error.getErrors() != null) {
149
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
150
System.err.println("Error Detail:");
151
System.err.println(" Domain: " + errorInfo.getDomain());
152
System.err.println(" Reason: " + errorInfo.getReason());
153
System.err.println(" Message: " + errorInfo.getMessage());
154
155
if (errorInfo.getLocation() != null) {
156
System.err.println(" Location: " + errorInfo.getLocation() +
157
" (" + errorInfo.getLocationType() + ")");
158
}
159
160
if (errorInfo.getExtendedHelp() != null) {
161
System.err.println(" Help: " + errorInfo.getExtendedHelp());
162
}
163
}
164
}
165
}
166
```
167
168
## Error Handling Patterns
169
170
### Specific Error Type Handlers
171
172
```java
173
// Handle validation errors
174
private void handleBadRequest(GoogleJsonError error) {
175
System.err.println("Validation Error: " + error.getMessage());
176
177
if (error.getErrors() != null) {
178
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
179
if ("invalid".equals(errorInfo.getReason())) {
180
System.err.println("Invalid field: " + errorInfo.getLocation());
181
} else if ("required".equals(errorInfo.getReason())) {
182
System.err.println("Missing required field: " + errorInfo.getLocation());
183
}
184
}
185
}
186
}
187
188
// Handle authentication errors
189
private void handleUnauthorized(GoogleJsonError error) {
190
System.err.println("Authentication failed: " + error.getMessage());
191
// Trigger token refresh or re-authentication
192
refreshAuthenticationToken();
193
}
194
195
// Handle permission errors
196
private void handleForbidden(GoogleJsonError error) {
197
System.err.println("Access forbidden: " + error.getMessage());
198
199
if (error.getErrors() != null) {
200
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
201
if ("insufficientPermissions".equals(errorInfo.getReason())) {
202
System.err.println("Missing permission: " + errorInfo.getMessage());
203
}
204
}
205
}
206
}
207
208
// Handle rate limiting
209
private void handleRateLimitExceeded(GoogleJsonError error) {
210
System.err.println("Rate limit exceeded: " + error.getMessage());
211
212
// Implement exponential backoff
213
try {
214
Thread.sleep(calculateRetryDelay());
215
// Retry the request
216
} catch (InterruptedException e) {
217
Thread.currentThread().interrupt();
218
}
219
}
220
```
221
222
### Retry Logic with Error Analysis
223
224
```java
225
public <T> T executeWithRetry(AbstractGoogleClientRequest<T> request, int maxRetries)
226
throws IOException {
227
228
int attempt = 0;
229
while (attempt < maxRetries) {
230
try {
231
return request.execute();
232
} catch (GoogleJsonResponseException e) {
233
attempt++;
234
235
// Determine if error is retryable
236
if (!isRetryableError(e) || attempt >= maxRetries) {
237
throw e;
238
}
239
240
// Calculate delay based on error type
241
long delay = calculateRetryDelay(e, attempt);
242
243
try {
244
Thread.sleep(delay);
245
} catch (InterruptedException ie) {
246
Thread.currentThread().interrupt();
247
throw new IOException("Interrupted during retry", ie);
248
}
249
}
250
}
251
252
throw new IOException("Maximum retries exceeded");
253
}
254
255
private boolean isRetryableError(GoogleJsonResponseException e) {
256
int statusCode = e.getStatusCode();
257
258
// Retryable HTTP status codes
259
if (statusCode == 429 || statusCode >= 500) {
260
return true;
261
}
262
263
// Check for specific retryable error reasons
264
GoogleJsonError error = e.getDetails();
265
if (error != null && error.getErrors() != null) {
266
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
267
String reason = errorInfo.getReason();
268
if ("rateLimitExceeded".equals(reason) ||
269
"userRateLimitExceeded".equals(reason) ||
270
"backendError".equals(reason)) {
271
return true;
272
}
273
}
274
}
275
276
return false;
277
}
278
279
private long calculateRetryDelay(GoogleJsonResponseException e, int attempt) {
280
// Base exponential backoff: 2^attempt * 1000ms
281
long baseDelay = (long) Math.pow(2, attempt) * 1000;
282
283
// Cap at 60 seconds
284
baseDelay = Math.min(baseDelay, 60000);
285
286
// Add jitter to prevent thundering herd
287
long jitter = (long) (Math.random() * 1000);
288
289
return baseDelay + jitter;
290
}
291
```
292
293
## Error Logging and Monitoring
294
295
### Structured Error Logging
296
297
```java
298
import java.util.logging.Logger;
299
import java.util.logging.Level;
300
301
private static final Logger logger = Logger.getLogger(MyApiClient.class.getName());
302
303
private void logApiError(GoogleJsonResponseException e) {
304
GoogleJsonError error = e.getDetails();
305
306
// Create structured log entry
307
StringBuilder logMessage = new StringBuilder();
308
logMessage.append("Google API Error - ");
309
logMessage.append("Status: ").append(e.getStatusCode()).append(" ");
310
logMessage.append("Message: ").append(e.getStatusMessage()).append(" ");
311
312
if (error != null) {
313
logMessage.append("Code: ").append(error.getCode()).append(" ");
314
logMessage.append("Details: ").append(error.getMessage());
315
316
if (error.getErrors() != null) {
317
logMessage.append(" Errors: [");
318
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
319
logMessage.append(errorInfo.getDomain())
320
.append("/")
321
.append(errorInfo.getReason())
322
.append(": ")
323
.append(errorInfo.getMessage())
324
.append("; ");
325
}
326
logMessage.append("]");
327
}
328
}
329
330
logger.log(Level.WARNING, logMessage.toString(), e);
331
}
332
```
333
334
### Error Metrics Collection
335
336
```java
337
// Example error metrics collection
338
public class ApiErrorMetrics {
339
private final Map<Integer, AtomicLong> statusCodeCounts = new ConcurrentHashMap<>();
340
private final Map<String, AtomicLong> errorReasonCounts = new ConcurrentHashMap<>();
341
342
public void recordError(GoogleJsonResponseException e) {
343
// Count by status code
344
statusCodeCounts.computeIfAbsent(e.getStatusCode(), k -> new AtomicLong(0))
345
.incrementAndGet();
346
347
// Count by error reason
348
GoogleJsonError error = e.getDetails();
349
if (error != null && error.getErrors() != null) {
350
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
351
String reason = errorInfo.getReason();
352
if (reason != null) {
353
errorReasonCounts.computeIfAbsent(reason, k -> new AtomicLong(0))
354
.incrementAndGet();
355
}
356
}
357
}
358
}
359
360
public void printMetrics() {
361
System.out.println("API Error Metrics:");
362
System.out.println("Status Codes:");
363
statusCodeCounts.forEach((code, count) ->
364
System.out.println(" " + code + ": " + count.get()));
365
366
System.out.println("Error Reasons:");
367
errorReasonCounts.forEach((reason, count) ->
368
System.out.println(" " + reason + ": " + count.get()));
369
}
370
}
371
```
372
373
## Types
374
375
### HttpResponseException
376
377
Base HTTP response exception class.
378
379
### HttpResponse
380
381
HTTP response representation.
382
383
### JsonFactory
384
385
JSON factory for parsing JSON content.
386
387
### GenericJson
388
389
Base class for JSON data models.
390
391
### IOException
392
393
Exception for I/O operations.
394
395
### List<T>
396
397
Java list interface for collections.
398
399
### Integer
400
401
Java integer wrapper class.
402
403
### String
404
405
Java string class.
406
407
### Logger
408
409
Java logging utility.
410
411
### Map<K,V>
412
413
Java map interface for key-value collections.
414
415
### AtomicLong
416
417
Thread-safe long counter for metrics.