You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot接口接收含单引号JSON请求报400错误的解决问询

解决SpringBoot中Jackson解析含单引号请求体的问题

首先,咱们来拆解你遇到的错误:JSON parse error: Unexpected end-of-input in VALUE_STRING,这个报错本质是Jackson在解析JSON时,把字符串里的单引号误判成了字符串的结束标记,导致解析到一半就认为字符串提前结束了。下面分两种常见场景给你解决方案:

场景1:请求体是合法JSON(双引号包裹字符串,内部含单引号)

如果你的请求体是标准JSON格式,比如{"name" : "peter o'toole"},这种情况下单引号属于字符串的合法内容,Jackson默认应该能正常解析。要是还是报错,先排查这几点:

  • 确认请求头的Content-Type是application/json,SpringBoot只会对这个类型的请求体用Jackson解析
  • 用JSON校验工具(比如在线的JSON校验器)检查请求体格式是否完全合法,有没有遗漏逗号、括号这类细节
  • 看看SpringBoot和Jackson的版本是否兼容,老旧版本可能存在解析bug

如果以上都没问题,你可以显式配置Jackson确保它允许字符串内部的单引号:

配置文件方式(application.properties)

# 开启宽松解析规则,避免因非核心格式问题报错
spring.jackson.deserialization.fail-on-unknown-properties=false
spring.jackson.parser.allow-unquoted-control-chars=true

配置类方式

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 允许字符串中包含未转义的控制字符(包括单引号)
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
        return objectMapper;
    }
}

场景2:请求体是非标准JSON(单引号包裹字符串/字段)

如果前端传的是非标准JSON,比如用单引号包裹字段或值:{'name' : 'peter o'toole'},这种格式本身不符合JSON规范,Jackson默认会拒绝解析。此时你可以配置Jackson允许单引号作为字符串分隔符,同时要求前端转义字符串内部的单引号(比如改成{'name' : 'peter o\'toole'})。

配置文件方式(application.properties)

# 允许用单引号代替双引号包裹字符串
spring.jackson.parser.allow-single-quotes=true
# 允许字段名不带引号(如果前端有这种写法的话)
spring.jackson.parser.allow-unquoted-field-names=true
# 允许用反斜杠转义任意字符,包括单引号
spring.jackson.parser.allow-backslash-escaping-any-character=true

配置类方式

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 允许单引号包裹字符串
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        // 允许字段名不带引号
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        // 允许反斜杠转义任意字符
        objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
        return objectMapper;
    }
}

极端临时方案:前端无法修改请求格式

如果前端完全没法调整请求格式,你可以通过自定义HttpMessageConverter预处理请求体,把非法的单引号转义或替换成双引号。但这种方式有风险,可能会破坏合法的JSON结构,只建议作为临时应急方法:

@Configuration
public class CustomJacksonHttpMessageConverterConfig {
    @Bean
    public MappingJackson2HttpMessageConverter customMappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        converter.setObjectMapper(objectMapper);

        // 自定义请求体预处理逻辑
        converter.setRequestBodyConverter(new HttpMessageConverter<Object>() {
            @Override
            public boolean canRead(Class<?> clazz, MediaType mediaType) {
                return converter.canRead(clazz, mediaType);
            }

            @Override
            public Object read(Class<?> clazz, HttpInputMessage inputMessage) throws IOException {
                // 读取原始请求体
                String rawBody = StreamUtils.copyToString(inputMessage.getBody(), StandardCharsets.UTF_8);
                // 替换字符串内部未转义的单引号(仅针对单引号包裹的字符串场景)
                String processedBody = rawBody.replaceAll("(?<!\\\\)'(?!([^']*'[^']*')*[^']*$)", "\\\\'");
                // 重新构造输入流
                ByteArrayInputStream inputStream = new ByteArrayInputStream(processedBody.getBytes(StandardCharsets.UTF_8));
                HttpInputMessage newInputMessage = new HttpInputMessage() {
                    @Override
                    public InputStream getBody() throws IOException {
                        return inputStream;
                    }

                    @Override
                    public HttpHeaders getHeaders() {
                        return inputMessage.getHeaders();
                    }
                };
                return converter.read(clazz, newInputMessage);
            }

            // 其他方法默认实现即可
            @Override
            public boolean canWrite(Class<?> clazz, MediaType mediaType) { return false; }
            @Override
            public List<MediaType> getSupportedMediaTypes() { return converter.getSupportedMediaTypes(); }
            @Override
            public void write(Object o, MediaType mediaType, HttpOutputMessage outputMessage) {}
        });

        return converter;
    }
}

提醒:这种自定义处理逻辑需要根据你的实际请求格式调整,否则可能引发新的解析问题,优先推荐前端修复JSON格式。

内容的提问来源于stack exchange,提问作者user2405589

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:01:43