google/gson · error · JsonSyntaxException
Failed parsing '${s}' as Currency; at path ${path}
Error message
Failed parsing '${s}' as Currency; at path ${path} What it means
Thrown by Gson's Currency TypeAdapter when java.util.Currency.getInstance cannot resolve the JSON string as an ISO 4217 currency code. Currency.getInstance throws IllegalArgumentException for unknown codes, which Gson wraps as a JsonSyntaxException. Note this adapter is nullSafe but does NOT consume a JSON null token explicitly in nextString().
Source
Thrown at gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java:815
}
@Override
public void write(JsonWriter out, UUID value) throws IOException {
out.value(value == null ? null : value.toString());
}
};
public static final TypeAdapterFactory UUID_FACTORY = newFactory(UUID.class, UUID);
public static final TypeAdapter<Currency> CURRENCY =
new TypeAdapter<Currency>() {
@Override
public Currency read(JsonReader in) throws IOException {
String s = in.nextString();
try {
return Currency.getInstance(s);
} catch (IllegalArgumentException e) {
throw new JsonSyntaxException(
"Failed parsing '" + s + "' as Currency; at path " + in.getPreviousPath(), e);
}
}
@Override
public void write(JsonWriter out, Currency value) throws IOException {
out.value(value.getCurrencyCode());
}
}.nullSafe();
public static final TypeAdapterFactory CURRENCY_FACTORY = newFactory(Currency.class, CURRENCY);
/**
* An abstract {@link TypeAdapter} for classes whose JSON serialization consists of a fixed set of
* integer fields. That is the case for {@link Calendar} and the legacy serialization of various
* {@code java.time} types.
*/
abstract static class IntegerFieldsTypeAdapter<T> extends TypeAdapter<T> {
private final List<String> fields;View on GitHub (pinned to 310ac341f2)
Solutions
- Ensure the JSON value is an uppercase ISO 4217 code (e.g. "USD", "EUR").
- Update the JDK / currency table (JDK holds the list in <jdk>/lib/currency.data) or run on a current JDK release so newer codes are recognized.
- Register a custom TypeAdapter<Currency> that uppercases the input and maps known aliases/symbols to Currency.getInstance codes.
- If only the symbol is available, deserialize as String and resolve through a lookup table in your domain code.
Example fix
// before
public class Price { public Currency currency; }
// JSON: {"currency":"usd"} -> fails (lowercase)
// after: normalize case with a custom adapter
Gson g = new GsonBuilder()
.registerTypeHierarchyAdapter(Currency.class, new TypeAdapter<Currency>() {
public Currency read(JsonReader in) throws IOException {
String s = in.nextString().trim().toUpperCase(Locale.ROOT);
return Currency.getInstance(s);
}
public void write(JsonWriter out, Currency v) throws IOException { out.value(v.getCurrencyCode()); }
}).create(); Defensive patterns
Strategy: validation
Validate before calling
private static final Set<String> ISO4217 =
Set.of("USD","EUR","GBP","JPY","CHF","CAD","AUD","CNY","INR","BRL","MXN"); // extend as needed
String raw = jsonNode.get("currency").getAsString();
if (raw == null || !ISO4217.contains(raw.trim().toUpperCase(Locale.ROOT))) {
throw new IllegalArgumentException("Unsupported currency code: " + raw);
}
// or rely on Currency.getAvailableCurrencies() at startup Try / catch
try {
return gson.fromJson(json, Price.class);
} catch (JsonSyntaxException e) {
if (e.getMessage().contains("as Currency")) {
throw new IllegalArgumentException("Unknown currency code", e);
}
throw e;
} Prevention
- Whitelist allowed currency codes from Currency.getAvailableCurrencies() at startup.
- Normalize case to uppercase before parsing.
- Never accept currency symbols ($) at the data layer; map them to ISO codes at ingestion.
- Run on a current JDK so newer ISO 4217 codes are recognized.
When it happens
Trigger: Deserializing a field of type java.util.Currency from a JSON string that is not a valid ISO 4217 code: lowercase ("usd" instead of "USD"), a 3-letter code not in the JDK's currency list, a currency symbol like "$", or a numeric code as a string.
Common situations: Mixing currency symbols ($) with ISO codes; receiving locale-formatted currency; new or unofficial ISO 4217 codes not yet in the running JDK's currency list; case-sensitive data sources emitting lowercase codes.
Related errors
- Failed parsing '${s}' as BigInteger; at path ${path}
- Failed parsing '${s}' as UUID; at path ${path}
- Failed parsing '${s}' as InetAddress; at path ${path}; to al
- Did not consume the entire document.
- Failed parsing JSON source: ${reader} to Json
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/532ae5b96b0de0bf.
Report an issue: GitHub.