public static JsonElement parseReader(Reader reader) throws JsonIOException, JsonSyntaxException {
    try {
      JsonReader jsonReader = new JsonReader(reader);
      JsonElement element = parseReader(jsonReader);
      if (!element.isJsonNull() && jsonReader.peek() != JsonToken.END_DOCUMENT) {
        throw new JsonSyntaxException("Did not consume the entire document.");
      }
      return element;
    } catch (MalformedJsonException e) {
      throw new JsonSyntaxException(e);
    } catch (IOException e) {
      throw new JsonIOException(e);
    } catch (NumberFormatException e) {
      throw new JsonSyntaxException(e);
    }
  }
@Test
  public void testParseDeeplyNestedObjects() throws IOException {
    int times = 10000;
    // {"a":{"a": ... {"a":null} ... }}
    String json = "{\"a\":".repeat(times) + "null" + "}".repeat(times);
    JsonReader jsonReader = new JsonReader(new StringReader(json));
    jsonReader.setNestingLimit(Integer.MAX_VALUE);

    int actualTimes = 0;
    JsonObject current = JsonParser.parseReader(jsonReader).getAsJsonObject();
    while (true) {
      assertThat(current.size()).isEqualTo(1);
      actualTimes++;
      JsonElement next = current.get("a");
      if (next.isJsonNull()) {
        break;
      } else {
        current = next.getAsJsonObject();
      }
    }
    assertThat(actualTimes).isEqualTo(times);
  }