Unrecognized token 'ename': was expecting ('true', 'false' or 'null')(ajax中data动态获取数据)

本文介绍了一种常见问题,即Ajax请求中dataType设置为json时,由于数据格式不规范导致success回调函数无法正常执行,而转为执行error回调的情况。通过调整发送的数据格式,使其符合严格的JSON规范,解决了该问题。
1.报错现象:

页面报错截图:
页面报错截图
后台报错截图:
后台报错截图

2.源代码:

jsp代码:

    $.ajax({ 
              type:"POST", 
              url:"${pageContext.request.contextPath }/empController/test", 
              contentType:"application/json;charset=utf-8",  //发送信息至服务器时内容编码类型。             

              data:{'ename':$('#ename').val()},
              dataType:'json',  
              success:function(data){ 
                        alert("保存....");
                      },
              error:function(data) { 
                        alert("失败...");
                    } 
          }); 

Controller代码:

    @ResponseBody
    @RequestMapping("/test")
    public Emp testjsp(@RequestBody Emp emp){
        System.out.println(emp.getEname()+"***************");
        return emp;
    }
3.问题分析:

返回数据格式不规范.当dataType指定为json后,1.4+以上的jquery版本对json格式要求更加严格.如果不是严格的json格式,就不能正常执行success回调函数.

JSON格式总结下,详细的去json.org 查看。   
1)键名称:用双引号 括起   
2)字符串:用使用双引号 括起
3)数字,布尔类型不需要 使用双引号 括起

4.解决方案:

按照上方严格的json格式,将动态获取的data参数修改为如下格式,即可:

data:"{\"ename\":\""+$("#ename").val()+"\"}",

不是动态获取数据时,格式如下:(注意比较区别)

data:'{"ename":"tom"}',
5.参考文章:

[1] ajax不执行success回调而是执行error回调

<think>我们正在处理一个不同的错误:之前的错误是关于日期反序列化(`Cannot deserialize value of type java.util.Date`),而现在的错误是`Unrecognized token 'Mon'`,这意味着Jackson在解析JSON时遇到了一个它不期望的令牌(token)'Mon'。 错误信息示例: Unrecognized token 'Mon': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false') 这个错误通常发生在以下情况: 1. 我们试图解析的文本根本不是合法的JSON。 2. 文本可能是JSONP(JSON with Padding)格式,例如:`callback({...})`,而不是纯JSON。 3. 文本中包含了Jackson无法识别的结构,比如未转义的特殊字符。 4. 可能是一个日期字符串(如"Mon Aug 11 16:53:58 CST 2025")被当成了JSON的字段名或其他结构。 根据错误信息中的`Unrecognized token 'Mon'`,我们可以推测,Jackson在解析时遇到了以“Mon”开头的字符串(可能是星期几的缩写),而它期望的是一个JSON值(字符串、数字、数组、对象或null/true/false)。 常见原因: - 尝试解析非JSON文本:例如,如果响应体是HTML、纯文本或JSONP,而不是纯JSON。 - JSON格式错误:比如缺少引号、括号不匹配等,导致Jackson在解析时遇到意外的字符。 - 日期字符串作为字段名:JSON要求字段名必须是字符串(用双引号括起来),如果字段名没有用引号括起来,而直接写`Mon ...`,则不是合法的JSON。 解决方案: 1. 检查返回的数据是否是合法的JSON: 使用在线JSON验证工具(如https://jsonlint.com/)或IDE的JSON格式化功能验证数据。 2. 如果返回的数据JSONP,则提取JSON部分: 例如,如果返回的数据是:`callback({ "key": "value" });`,我们需要去掉`callback(`和结尾的`);`,只保留`{ "key": "value" }`。 3. 检查JSON中的字段名是否用双引号括起来: 合法的JSON要求所有字段名都用双引号括起来,而不是单引号或无引号。例如: 错误:{ name: "John" } -> 应该改为 { "name": "John" } 4. 检查字符串值是否被正确转义: 如果字符串值中包含双引号,应该使用反斜杠进行转义,例如:`"quote\": \"This is a quote.\""` 5. 如果错误发生在反序列化日期字段时,注意日期字符串应该被双引号包围(作为JSON字符串): 正确:`"dateField": "Mon, 11 Aug 2025 16:53:58 CST"` 错误:`"dateField": Mon, 11 Aug 2025 16:53:58 CST` (缺少双引号,整个值不是字符串) 6. 如果日期字符串作为字段值,但缺少双引号,那么整个值就不是一个字符串,而会被解析为多个token(Mon被当作一个独立的token,而Jackson无法识别)。 7. 在代码中捕获并检查响应内容: 在出现异常时,打印出接收到的原始响应内容,以便分析。 8. 使用ObjectMapper配置来允许单引号(不推荐,因为不符合标准): 如果确实无法改变数据源,可以配置Jackson允许使用单引号: ```java ObjectMapper mapper = new ObjectMapper(); mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); ``` 9. 如果数据源不可控,尝试在解析前清理响应内容: 例如,移除JSONP包装,或者修复明显的格式错误。 示例错误场景: 假设我们期望的JSON是: { "date": "Mon, 11 Aug 2025 16:53:58 CST" } 但如果实际返回的是: { "date": Mon, 11 Aug 2025 16:53:58 CST } 那么,由于日期值没有用引号括起来,Jackson会尝试将`Mon`解释为一个值(但`Mon`不是合法的JSON值类型),因此报错。 因此,根本的解决方法是确保数据源返回合法的JSON。如果数据源不可控,我们可能需要在解析前对字符串进行预处理,例如在值上添加缺失的引号(但这很危险,因为值内部可能包含逗号、冒号等,所以最好从源头修复)。 步骤总结: 1. 捕获并打印完整的响应内容(在异常处理中)。 2. 验证响应内容是否为合法的JSON。 3. 如果不是,检查是否是JSONP,并提取JSON部分。 4. 检查是否有明显的格式错误,如字段名或字符串值缺少引号。 5. 如果无法改变数据源,考虑预处理响应字符串或配置ObjectMapper(如允许单引号)来容忍一些非标准格式。 代码示例(捕获异常并打印响应内容): ```java try { YourObject obj = objectMapper.readValue(responseContent, YourObject.class); } catch (JsonParseException e) { // 打印响应内容的前1000个字符以便分析 System.err.println("Invalid JSON: " + responseContent.substring(0, Math.min(1000, responseContent.length()))); throw e; } ``` 相关问题: 1. 如何验证JSON的合法性? 2. 如何处理JSONP响应? 3. Jackson ObjectMapper 的配置选项有哪些? 4. 如何在Spring Boot中全局处理JSON解析异常? 5. 常见的JSON格式错误有哪些?</think>### 解决 Jackson "Unrecognized token 'Mon'" 错误 #### 问题分析 当 Jackson 遇到错误 `Unrecognized token 'Mon': expecting JSON String Number Array Object or token 'null' 'true' or 'false'` 时,通常表示: 1. **非 JSON 数据**:尝试解析的文本不是有效的 JSON 格式 2. **日期格式问题**:`Mon` 是日期字符串的星期缩写(如 `Mon Aug 11 16:53:58 CST 2025`),但未正确标记为字符串值 3. **JSON 语法错误**:关键位置缺少引号、括号或逗号 4. **数据源问题**:可能接收到 HTML 错误页面、纯文本或格式错误的 API 响应 --- ### 解决方案(逐步排查) #### 步骤 1:验证 JSON 合法性 使用在线工具(如 [JSONLint](https://jsonlint.com/))检查原始响应内容: ```json // 错误示例(缺少引号) { date: Mon Aug 11 16:53:58 CST 2025 // ❌ 未加引号 } // 正确格式 { "date": "Mon Aug 11 16:53:58 CST 2025" // ✅ 字符串值必须用双引号 } ``` #### 步骤 2:检查数据源 在代码中打印原始响应: ```java // 对于 Spring Boot 应用 try { // 反序列化代码... } catch (JsonParseException e) { System.err.println("原始响应内容: " + responseBodyString); // 打印原始内容 throw e; } ``` *如果输出包含 HTML 标签(如 `<html>`)或纯文本,说明后端返回了错误页面而非 JSON* #### 步骤 3:处理日期字段 当日期值以 `Mon` 开头时,需明确标记为字符串并指定格式: ```java public class RequestDTO { @JsonFormat(pattern = "EEE MMM dd HH:mm:ss zzz yyyy", timezone = "GMT+8") private Date eventDate; // 处理 "Mon Aug 11 16:53:58 CST 2025" 格式 } ``` *格式说明*:`EEE`=星期缩写, `MMM`=月份缩写, `zzz`=时区 #### 步骤 4:配置 Jackson 容错机制 在 Spring Boot 中全局配置: ```java @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { return new ObjectMapper() // 允许未加引号的字段名(不推荐) .enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES) // 允许单引号 .enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES) // 忽略未知属性 .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); } } ``` #### 步骤 5:预处理非常规 JSON 对于非标准响应(如 JSONP),使用字符串处理: ```java String jsonp = "callback({ 'date': 'Mon Aug 11...' })"; // 提取 JSON 部分 String pureJson = jsonp.substring( jsonp.indexOf('{'), jsonp.lastIndexOf('}') + 1 ); YourDTO dto = objectMapper.readValue(pureJson, YourDTO.class); ``` --- ### 常见错误场景及修复 | **错误场景** | **修复方案** | **示例** | |------------|------------|---------| | 未加引号的字符串值 | 添加双引号 | `{ date: Mon... }` → `{ "date": "Mon..." }` | | 日期作为字段名 | 交换键值位置 | `{ Mon Aug... : value }` → `{ "eventDate": "Mon Aug..." }` | | 包含 HTML 的错误响应 | 检查 API 状态码 | 先验证 `response.getStatus() == 200` | | 单引号字符串 | 配置 `ALLOW_SINGLE_QUOTES` 或替换为双引号 | `{ 'date': ... }` → `{ "date": ... }` | | 尾部分隔符问题 | 删除多余逗号 | `{ "a":1, "b":2, }` → 移除最后一个逗号 | --- ### 根本原因分析 1. **JSON 规范要求**: - 所有字符串必须用 **双引号** `"` 包裹 - 字段名必须是字符串(如 `"fieldName"`) - 值只能是 JSON 数据类型:字符串、数字、对象、数组、布尔值、null ```json // 非法 JSON - Mon 被识别为未定义token { date: Mon Aug 11 16:53:58 CST 2025 } // 合法 JSON { "date": "Mon Aug 11 16:53:58 CST 2025" } ``` 2. **Jackson 解析流程**: ```mermaid graph LR A[输入流] --> B[词法分析] B -->|遇到 Mon| C{是否合法token?} C -->|是| D[继续解析] C -->|否| E[抛出 JsonParseException] E --> F[报错:Unrecognized token 'Mon'] ``` --- ### 测试验证方法 ```java // 测试错误格式 String badJson = "{ date: Mon Aug 11 16:53:58 CST 2025 }"; try { objectMapper.readValue(badJson, DTO.class); } catch (JsonParseException e) { System.out.println("捕获到预期异常: " + e.getMessage()); } // 测试正确格式 String goodJson = "{ \"date\": \"Mon Aug 11 16:53:58 CST 2025\" }"; DTO dto = objectMapper.readValue(goodJson, DTO.class); assertNotNull(dto.getDate()); ``` --- ### 相关问题 1. 如何在 Spring Boot 中全局处理 JSON 解析异常?[^2] 2. Jackson 如何配置以兼容非标准 JSON 格式? 3. 如何区分 `JsonParseException` 和 `JsonMappingException`? 4. 使用 `java.time` 替代 `java.util.Date` 能否避免此类问题?[^1] 5. 如何安全地处理第三方 API 返回的非 JSON 响应? [^1]: 日期处理需明确格式和时区 [^2]: Spring Boot 会封装原始 Jackson 异常
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值