easy-es Map类型字段序列化问题:Unexpected character (‘n‘ (code 110)):

@Data
@IndexName("demo")
public class EasyEsDemo {

    @IndexId
    private String id;

    private String name;
    private int age;

    // 这个Map字段因为NameFilter过滤器,导致fastjson序列化后为{null:"value"}这种形式,insert报错
    private Map<String, Object> data;
}

上面Map类型字段保存报错如下:

Caused by: ElasticsearchException[Elasticsearch exception [type=json_parse_exception, reason=Unexpected character ('n' (code 110)): was expecting double-quote to start field name
.....

此错误主要原因是:EntityInfoHelper中创建的NameFilter是一个匿名类,看上去主要功能就是过滤排除字段,但是针对Map类型字段就出现了问题,导致序列化时候Map的key字段变成了个null. 导致fastjson序列化后为{null:"value"}这种形式,insert报错。

EntityInfoHelper中NameFilter过滤器代码如下:这个过滤器导致序列化Map类型字段时,获取的key当成类的字段属性处理,而类中没有名字为key的字段,所以过滤器过滤完后key变成了null

    /**
     * 添加fastjson字段过滤器
     *
     * @param entityInfo 实体信息
     */
    private static void addNameFilter(EntityInfo entity
<think>我们正在处理一个关于Postman使用form-data传递参数导致JSON解析错误的问题。根据引用[1]和引用[2]中的错误信息,我们可以分析如下: 1. 引用[1]中的错误信息:`JSON parse error: Unexpected character ('-' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value;` - 这个错误表明在解析JSON时,在数值中遇到了一个减号('-'),但是减号后面没有紧跟数字(0-9),因此不是一个有效的数值。这通常发生在传递的JSON数据格式不正确的情况下。 2. 引用[2]中的错误信息:`"message":"Invalid mime type \"application/json, application/x-www-form-urlencoded\": Invalid token character ',' in token \"json, application/x-www-form-urlencoded\""` - 这个错误指出请求的媒体类型(Content-Type)无效,因为同时指定了两种媒体类型(用逗号分隔),这是不允许的。HTTP规范要求`Content-Type`头只能指定一个媒体类型。 结合用户的问题描述:“Postman form-data 参数传递导致 JsonParseException Unexpected character '-' in numeric value”,我们可以推断: - 用户可能在使用Postman发送请求时,选择了`form-data`格式传递参数,但是后端接口期望的是JSON格式(因为使用了`@RequestBody`注解)。 - 由于使用了`form-data`,请求体并不是JSON格式,而是多部分表单数据(multipart/form-data),因此后端在尝试将表单数据解析为JSON时失败,导致出现上述异常。 ### 问题原因分析 1. **后端接口设计**:后端接口使用`@RequestBody`注解,这意味着它期望请求体是JSON格式,并且Spring会尝试将请求体解析为`StudentDTO`对象。 2. **前端请求设置**:用户使用Postman发送请求时,选择了`form-data`格式,这会导致请求的`Content-Type`为`multipart/form-data`(或`application/x-www-form-urlencoded`,取决于具体选择),而不是`application/json`。 3. **数据格式不匹配**:当请求体是`form-data`格式时,Spring无法用JSON解析器去解析,因此会抛出`HttpMessageNotReadableException`,具体原因可能是解析器在尝试解析表单数据时遇到了非预期的字符(比如在数值字段中出现了单独的减号,而没有紧跟数字)。 ### 解决方案 要解决这个问题,有以下两种方法: #### 方法一:修改前端请求,发送JSON格式数据 1. 在Postman中,将请求体格式改为`raw`,然后选择`JSON`格式。 2. 在请求体中输入符合`StudentDTO`结构的JSON数据,例如: ```json { "id": 123, "name": "张三" } ``` 3. 设置请求头`Content-Type`为`application/json`(Postman在选择`raw`和`JSON`后通常会自动设置)。 #### 方法二:修改后端接口,支持表单数据 如果希望后端接口能够接收`form-data`或`x-www-form-urlencoded`格式的数据,需要做以下修改: 1. 移除`@RequestBody`注解,因为该注解用于请求体是JSON或XML等格式的情况。 2. 使用`@RequestParam`注解或直接使用对象参数(无需注解)来接收表单数据。 例如,修改后的接口可以这样写: ```java @RequestMapping("/get/test1") @GetMapping public String testGETRequestParam(StudentDTO dto) { dto.setId(dto.getId()); dto.setName(dto.getName()); return dto.toString(); } ``` 这样,Spring就会将表单参数映射到`StudentDTO`对象的属性上。 ### 注意事项 - 如果使用`@RequestBody`,则必须发送JSON格式的请求体,且`Content-Type`为`application/json`。 - 如果使用`form-data`,则不能使用`@RequestBody`,而应该使用`@RequestParam`或直接使用对象接收(不带注解)。 ### 总结 用户的问题是由于请求格式与后端接口期望的格式不匹配造成的。用户需要根据后端接口的设计,在Postman中选择正确的请求格式(JSON或表单数据),或者修改后端接口以支持表单数据。 §§相关问题§§ 1. 如何在Postman中正确发送JSON格式的请求? 2. Spring MVC中`@RequestBody`和`@RequestParam`有什么区别? 3. 如何在后端同时支持JSON和表单数据的请求?</think>### Postman form-data 参数传递导致 JSON 解析错误分析 #### 问题原因 当使用 Postman 发送 `form-data` 格式请求时,后端出现 `Unexpected character '-' in numeric value` 错误,主要原因是: 1. **Content-Type 冲突** `@RequestBody` 注解要求请求体必须是纯 JSON 格式,但 `form-data` 会生成类似以下结构的多部分数据: ```http ------WebKitFormBoundary Content-Disposition: form-data; name="id" 123 ------WebKitFormBoundary Content-Disposition: form-data; name="name" John ``` 这与 JSON 解析器期望的 `{"id":123,"name":"John"}` 结构冲突[^1][^2]。 2. **数据类型不匹配** 错误信息 `Unexpected character '-'` 表明解析器在数值字段中遇到了非数字字符(如 `-`),这通常发生在: - 数字字段被误传为字符串(如 `"age":"-25"` 而非 `"age":-25`) - 表单数据包含未处理的特殊字符 3. **请求头错误** 当同时指定多个 `Content-Type`(如 `application/json, application/x-www-form-urlencoded`)时,会触发 `Invalid token character ','` 错误[^2]。 --- ### 解决方案 #### 方法一:修改请求格式(推荐) 1. 在 Postman 中: - 切换 Body 类型为 **raw** - 选择格式为 **JSON** - 输入合法 JSON: ```json { "id": 123, "name": "John" } ``` - 设置 Header:`Content-Type: application/json` #### 方法二:后端适配 form-data 修改 Controller,移除 `@RequestBody`: ```java @GetMapping("/get/test1") public String testGETRequestParam(StudentDTO dto) { // 移除 @RequestBody return dto.toString(); } ``` 此时支持以下格式: - `form-data` - `x-www-form-urlencoded` #### 方法三:处理数据类型异常 在 DTO 中明确数值类型,避免字符串/数字混淆: ```java public class StudentDTO { private Integer id; // 必须使用包装类型 private String name; // Getter/Setter } ``` --- ### 关键验证步骤 1. **检查 Postman 设置** ![Postman 设置对比](https://example.com/postman-comparison.png) *左:错误 form-data 示例 | 右:正确 JSON 格式* 2. **后端日志诊断** 启用 Spring Boot 调试日志: ```properties logging.level.org.springframework.web=DEBUG logging.level.org.springframework.http=TRACE ``` --- ### 技术原理 - **`@RequestBody` 要求**:只能解析 `application/json` 或 `application/xml` 等结构化数据 - **form-data 本质**:多部分二进制流,需用 `@RequestPart` 或 `MultipartFile` 处理 - **JSON 语法规范**:数值字段禁止包含非数字字符(如 `-` 后接非数字)[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值