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
- Sanitize the source string to ASCII before deserialization, or fix the producing system to emit plain ASCII numeric literals.
- Change the target field type to String and parse it yourself with a NumberFormat that handles the locale, then convert to long/int.
- Register a custom TypeAdapter<Long> that strips non-ASCII and uses Long.parseLong, or use @JsonAdapter to attach it per field.
- 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
- Validate incoming numeric strings at the API boundary; reject or normalize non-ASCII.
- Prefer numeric JSON literals (unquoted) over strings when you control the producer.
- Type ambiguous numeric fields as String and parse explicitly with locale-aware NumberFormat.
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
- JSON forbids NaN and infinities: {value}
- Expecting number, got: " + jsonToken + "; at path " + in.get
- Numeric values must be finite, but was " + string
- String created by " + numberClass + " is not a valid JSON nu
- ${message}${locationString()} See ${TroubleshootingGuide.cre
AI-assisted analysis of google/gson@8b8628c656 (2026-08-04).
Data as JSON: /data/errors/5f17c983bfec99ee.json.
Report an issue: GitHub.