使用Google GSON解析JSON请求时遭遇语法错误求助
我一开始尝试解析这段JSON请求:
{"action":"ProjectCreation", data:{"projectName": "test project"}}
当时没发现语法问题,但GSON抛出了错误:
Exception in thread "main" com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Unterminated object at line 1 column 20 path $
后来我修正了JSON,给data加上双引号,变成:
{"action":"ProjectCreation", "data":{"projectName": "test project"}}
可GSON还是报一模一样的错误。负责解析的代码如下:
private Type type = new TypeToken<Map<String, Object>>(){}.getType(); private String action; private String responseAction; private Map<String, String> data; private Type dataType = new TypeToken<Map<String, String>>(){}.getType(); private Gson gson = new Gson(); private String requestId; private Client client = new Client("127.0.0.1", 5699); /** * Constructor for this class, sets initial parameters * @param request * @param _requestId */ public ActionThread(String request, String _requestId) { System.out.println(request); //Parse the request into a map Map<String, Object> _request = gson.fromJson(request, type); //Give action the correct naming convention action = _request.get("action") + "Request"; responseAction = _request.get("action") + "Response"; //Parse the data into a map String _data = _request.get("data").toString(); data = gson.fromJson(_data, dataType); //Set the request id requestId = _requestId; }
问题根源与解决方案
嘿,其实你的JSON已经没问题了,错误出在解析代码的逻辑上!重点看这两行:
String _data = _request.get("data").toString(); data = gson.fromJson(_data, dataType);
当你用gson.fromJson(request, type)把整个请求解析成Map<String, Object>后,_request.get("data")拿到的已经是GSON自动生成的LinkedTreeMap对象了。这时候你调用toString()方法,得到的字符串根本不是标准JSON格式——它会变成类似{projectName=test project}这样的样子,用的是等号而不是冒号,键也没有双引号,这当然会让GSON再次解析时报语法错误。
两种修复方案任你选:
方案一:直接类型转换(快速修复)
既然data本身就是一个Map,直接把它转成Map<String, String>就行,不用再转成字符串重新解析:
// 替换原来的data解析代码 data = (Map<String, String>) _request.get("data");
⚠️ 注意:如果data里存在非String类型的值,可能会抛出类型转换异常,需要根据你的实际数据结构调整。
方案二:用实体类解析(更规范)
创建一个和请求结构对应的实体类,这样类型更安全,代码也更清晰:
// 定义请求实体类 class ProjectRequest { private String action; private Map<String, String> data; // 生成getter和setter方法 public String getAction() { return action; } public void setAction(String action) { this.action = action; } public Map<String, String> getData() { return data; } public void setData(Map<String, String> data) { this.data = data; } }
然后在构造方法里直接解析到这个类:
public ActionThread(String request, String _requestId) { System.out.println(request); // 直接解析到实体类 ProjectRequest _request = gson.fromJson(request, ProjectRequest.class); // 后续操作直接用实体类的getter action = _request.getAction() + "Request"; responseAction = _request.getAction() + "Response"; data = _request.getData(); requestId = _requestId; }
这种方式不仅能彻底解决当前的问题,还能让代码更易维护,后续扩展字段也更方便。
内容的提问来源于stack exchange,提问作者Jojo01

