{"record":{"id":"7409c8c7edd3f077","repo":"google/gson","slug":"expecting-character-got-str-at-path","errorCode":null,"errorMessage":"Expecting character, got: ${str}; at ${path}","messagePattern":"Expecting character, got: (.+?); at (.+?)","errorType":"exception","errorClass":"JsonSyntaxException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java","lineNumber":544,"sourceCode":"  }\n\n  public static final TypeAdapter<Number> FLOAT = new FloatAdapter(false);\n  public static final TypeAdapter<Number> FLOAT_STRICT = new FloatAdapter(true);\n\n  public static final TypeAdapter<Number> DOUBLE = new DoubleAdapter(false);\n  public static final TypeAdapter<Number> DOUBLE_STRICT = new DoubleAdapter(true);\n\n  public static final TypeAdapter<Character> CHARACTER =\n      new TypeAdapter<Character>() {\n        @Override\n        public Character read(JsonReader in) throws IOException {\n          if (in.peek() == JsonToken.NULL) {\n            in.nextNull();\n            return null;\n          }\n          String str = in.nextString();\n          if (str.length() != 1) {\n            throw new JsonSyntaxException(\n                \"Expecting character, got: \" + str + \"; at \" + in.getPreviousPath());\n          }\n          return str.charAt(0);\n        }\n\n        @Override\n        public void write(JsonWriter out, Character value) throws IOException {\n          out.value(value == null ? null : String.valueOf(value));\n        }\n      };\n\n  public static final TypeAdapterFactory CHARACTER_FACTORY =\n      newFactory(char.class, Character.class, CHARACTER);\n\n  public static final TypeAdapter<String> STRING =\n      new TypeAdapter<String>() {\n        @Override\n        public String read(JsonReader in) throws IOException {","sourceCodeStart":526,"sourceCodeEnd":562,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java#L526-L562","documentation":"The CHARACTER adapter reads a JSON string and expects exactly one character. If the string is empty or has more than one character, Gson cannot unambiguously map it to a char and throws JsonSyntaxException.","triggerScenarios":"Deserializing a JSON string like \"\" (empty) or \"ab\" (two chars) into a char or Character field.","commonSituations":"An API returns an empty string for an optional char field; a multi-character string is mistakenly mapped to a char field; enum-like codes longer than one character modeled as char.","solutions":["Change the field type from char/Character to String to accept variable-length values","Pre-validate that the JSON string has exactly one character before deserializing","Register a custom TypeAdapter that takes the first character or provides a default"],"exampleFix":"// before\nclass Config { char grade; }\ngson.fromJson(\"{\\\"grade\\\":\\\"A+\\\"}\", Config.class); // throws — two chars\n\n// after\nclass Config { String grade; }","handlingStrategy":"validation","validationCode":"// Validate that the JSON value is a single character before deserializing into char\npublic static boolean isSingleChar(JsonElement e) {\n    return e.isJsonPrimitive() && e.getAsString().length() == 1;\n}","typeGuard":null,"tryCatchPattern":"try {\n    Config c = gson.fromJson(json, Config.class);\n} catch (JsonSyntaxException e) {\n    if (e.getMessage().contains(\"Expecting character\")) {\n        // change the field type to String or pre-validate input\n    }\n}","preventionTips":["Use String instead of char for fields that may receive multi-character or empty values","Validate single-character constraints at the API boundary","Document char fields as strictly single-character in API contracts"],"tags":["deserialization","character","validation","json-syntax"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}