google/gson · error · MalformedJsonException

String contains non-ASCII characters: {s}{location}

Error message

String contains non-ASCII characters: {s}{location}

What it means

Thrown by JsonTreeReader.validateAscii() when nextLong() or nextInt() reads a STRING token whose content contains characters above code point 127. Gson only attempts ASCII numeric coercion for string-encoded numbers; any non-ASCII byte (e.g. Unicode digits, whitespace, or unit suffixes) is treated as malformed. It is a MalformedJsonException because the data cannot be parsed as the requested numeric type under strict ASCII rules.

Source

Thrown at gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java:431

  }

  private String locationString() {
    return " at path " + getPath();
  }

  /** Returns whether every character of {@code s} is ASCII (code point at most 127). */
  public static boolean isAllAscii(String s) {
    for (int i = 0; i < s.length(); i++) {
      if (s.charAt(i) > 127) {
        return false;
      }
    }
    return true;
  }

  private void validateAscii(String s) throws MalformedJsonException {
    if (!isAllAscii(s)) {
      throw new MalformedJsonException(
          "String contains non-ASCII characters: " + s + locationString());
    }
  }

  /** Creates a {@link NumberFormatException} whose message includes the current path. */
  private NumberFormatException numberFormatException(String message, NumberFormatException cause) {
    NumberFormatException exception = new NumberFormatException(message + locationString());
    exception.initCause(cause);
    return exception;
  }
}

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Sanitize the source string to ASCII before deserialization, or fix the producing system to emit plain ASCII numeric literals.
  2. Change the target field type to String and parse it yourself with a NumberFormat that handles the locale, then convert to long/int.
  3. Register a custom TypeAdapter<Long> that strips non-ASCII and uses Long.parseLong, or use @JsonAdapter to attach it per field.
  4. If the value is genuinely numeric but Unicode-encoded, normalize via StringNormalizer (NFKC) to ASCII digits before parsing.

Example fix

// before: field is long but JSON has "\u0661\u0662" (Arabic 12) -> throws
class Data { long count; }

// after: accept String, normalize, parse manually
class Data {
  String count;
  long getCount() {
    return Long.parseLong(java.text.Normalizer.normalize(count, java.text.Normalizer.Form.NFKC)
        .replaceAll("[^0-9-]", ""));
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate ASCII-ness of a string before it is read as a number
if (reader.peek() == JsonToken.STRING) {
  String s = reader.nextString();
  if (!JsonTreeReader.isAllAscii(s)) {
    s = java.text.Normalizer.normalize(s, java.text.Normalizer.Form.NFKC).replaceAll("[^\\x00-\\x7F]", "");
  }
  return Long.parseLong(s);
}

Try / catch

try {
  return reader.nextLong();
} catch (MalformedJsonException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("String contains non-ASCII")) {
    // fall back to String + manual normalization
    String s = reader.nextString();
    return Long.parseLong(java.text.Normalizer.normalize(s, java.text.Normalizer.Form.NFKC).replaceAll("[^0-9-]", ""));
  }
  throw e;
}

Prevention

When it happens

Trigger: Deserializing a field declared as long/int whose JSON value is a quoted string containing non-ASCII characters (e.g. "\u0661\u0662" Arabic-Indic digits, "123" fullwidth digits, a value with a stray BOM or currency symbol). The path is only exercised when peek()==STRING in nextLong()/nextInt(), which happens when Gson reads a string-typed JSON value into a numeric Java field.

Common situations: Locale-specific numeric strings from external APIs (fullwidth digits from Japanese/Chinese systems, Arabic-Indic digits); copy-paste introducing zero-width or BOM characters; data exported from spreadsheets that embed currency/grouping symbols; misconfigured encodings where binary garbage lands in a numeric field.

Related errors


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