google/gson · error · MalformedJsonException
String contains non-ASCII characters: ${s} at path ${path}
Error message
String contains non-ASCII characters: ${s} at path ${path} What it means
JsonTreeReader (Gson's reader over an in-memory JsonElement tree) calls validateAscii() inside nextInt() and nextLong() when the current token is a STRING being coerced to a number. If any character has a code point above 127 (e.g. full-width CJK digits like '123'), Gson throws MalformedJsonException because such strings cannot be reliably parsed as a Java integer. The guard exists because non-ASCII numeric characters would otherwise yield silent, wrong numeric results.
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 310ac341f2)
Solutions
- Normalize the offending string to ASCII before parsing, e.g. java.text.Normalizer.normalize(s, Normalizer.Form.NFKC) to fold full-width digits to ASCII
- Write a custom TypeAdapter<Integer>/<Long> (registered via GsonBuilder.registerTypeAdapter) that pre-normalizes the string
- Fix the data at its origin to emit ASCII digit characters (0-9)
Example fix
// before - throws on JsonPrimitive("123")
int v = jsonElement.getAsInt();
// after - normalize full-width digits to ASCII first
String s = jsonElement.getAsString();
s = java.text.Normalizer.normalize(s, java.text.Normalizer.Form.NFKC);
int v = Integer.parseInt(s); Defensive patterns
Strategy: validation
Validate before calling
// Before parsing a string token as int/long, verify ASCII
import com.google.gson.internal.bind.JsonTreeReader;
String s = jsonPrimitive.getAsString();
if (!JsonTreeReader.isAllAscii(s)) {
s = java.text.Normalizer.normalize(s, java.text.Normalizer.Form.NFKC);
}
int value = Integer.parseInt(s); // safe now Try / catch
try {
int v = gson.fromJson(jsonElement, Integer.class);
} catch (com.google.gson.stream.MalformedJsonException e) {
// message indicates non-ASCII; normalize source and retry, or fall back
} Prevention
- Normalize all incoming numeric strings to ASCII (NFKC) at the ingestion boundary
- Validate that numeric source fields contain only ASCII digits before they reach Gson
- Add unit tests with full-width and locale-specific digit inputs
When it happens
Trigger: Deserializing a JsonElement tree into an int/long field where the JSON value is a string token containing non-ASCII characters; calling nextInt()/nextLong() directly on a JsonReader wrapping a JsonPrimitive string with Unicode digits; data produced by CJK-localized systems emitting full-width numerals.
Common situations: Internationalized data from Japanese/Chinese/Korean locales using full-width digits; copy-paste from office suites that auto-convert ASCII digits to typographic Unicode forms; JSON received from systems that localize number formatting.
Related errors
- JSON forbids NaN and infinities: ${d}; at path ${in.getPrevi
- Cannot parse ${value}; at path ${in.getPreviousPath()}
- duplicate key: ${key}
- Expecting number, got: ${jsonToken}; at path ${path}
- Unexpected token: ${peeked}
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/8e3398544d7a3e4f.
Report an issue: GitHub.