google/gson · error · JsonSyntaxException

Expecting number, got: " + jsonToken + "; at path " + in.get

Error message

Expecting number, got: " + jsonToken + "; at path " + in.getPath()

What it means

Thrown by NumberTypeAdapter.read() as a JsonSyntaxException when deserializing into java.lang.Number and the current token is not NULL, NUMBER, or STRING. The adapter accepts a quoted numeric string (STRING) and plain numbers, but booleans, objects, arrays, names, and end tokens cannot be coerced to Number.

Source

Thrown at gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java:73

    if (toNumberStrategy == ToNumberPolicy.LAZILY_PARSED_NUMBER) {
      return LAZILY_PARSED_NUMBER_FACTORY;
    } else {
      return newFactory(toNumberStrategy);
    }
  }

  @Override
  public Number read(JsonReader in) throws IOException {
    JsonToken jsonToken = in.peek();
    switch (jsonToken) {
      case NULL:
        in.nextNull();
        return null;
      case NUMBER:
      case STRING:
        return toNumberStrategy.readNumber(in);
      default:
        throw new JsonSyntaxException(
            "Expecting number, got: " + jsonToken + "; at path " + in.getPath());
    }
  }

  @Override
  public void write(JsonWriter out, Number value) throws IOException {
    out.value(value);
  }
}

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Correct the source data so the value at that path is a number or numeric string.
  2. Change the target field type to match the actual JSON value (Boolean, Object, String), or use Object to accept any primitive.
  3. Register a custom TypeAdapter<Number> that coerces allowed alternatives (e.g. treat booleans as 1/0) if that semantics is intended.
  4. Configure a more lenient object/number policy (GsonBuilder.setObjectToNumberStrategy) if the issue is at the Object level.

Example fix

// before
// JSON: true
class Data { Number n; }
Data d = gson.fromJson("{\"n\":true}", Data.class); // throws: Expecting number, got: BOOLEAN

// after: match the type to the data
class Data { Boolean n; } // or Object n; or String n;
Data d = gson.fromJson("{\"n\":true}", Data.class);
Defensive patterns

Strategy: validation

Validate before calling

// Peek and validate token shape before reading as Number
JsonToken t = reader.peek();
if (t != JsonToken.NUMBER && t != JsonToken.STRING && t != JsonToken.NULL) {
  throw new IllegalStateException("Not a number: " + t);
}
Number n = gson.getAdapter(Number.class).read(reader);

Try / catch

try {
  return gson.fromJson(json, Number.class);
} catch (JsonSyntaxException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Expecting number, got:")) {
    // value isn't numeric; fall back to Object or String
    return gson.fromJson(json, Object.class);
  }
  throw e;
}

Prevention

When it happens

Trigger: Deserializing JSON where a Number-typed field (or Number.class target) receives a non-numeric value: a boolean (true/false), an object {}, an array [], etc. For example, a field declared as Number receiving {"val":true} or a JSON value of true at that position.

Common situations: Loosely-typed domain models using Number as a catch-all then receiving boolean markers from an API; schema drift where a numeric field becomes an object; wrong target type passed to fromJson (e.g. fromJson("true", Number.class)); producers sending null vs absent vs boolean inconsistently.

Related errors


AI-assisted analysis of google/gson@8b8628c656 (2026-08-04). Data as JSON: /data/errors/da957932e0f0bb3d.json. Report an issue: GitHub.