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

如何正确反序列化含JHipster StringFilter的Criteria DTO

问题根因

你接收到的criteria参数值是Java对象执行toString()方法生成的普通文本,格式为类名(属性1=值, 属性2=值),既不是标准JSON结构,也不是Spring MVC默认支持的表单键值对格式。
不管是Spring内置的请求参数绑定,还是你手动写的Jackson反序列化逻辑,默认都只能识别JSON、扁平表单键值对格式的输入,根本无法解析这种toString输出的文本,所以不管你给DocCriteria加多少Jackson、Lombok注解,都会出现字段全为null的情况,甚至直接抛出反序列化异常。
另外补充:JHipster框架自带的Criteria类原生就有适配Spring MVC的参数绑定规则,设计上就不要求把整个Criteria对象转成字符串塞到单个参数里传递,你当前遇到的问题本质是传参方式和框架预期不匹配。

解决方案

根据调用方是否可以调整传参逻辑,二选一即可:

方案1:可调整调用方逻辑时,按JHipster原生规范传参(优先推荐,无额外维护成本)

直接让调用方把筛选条件拆成扁平的查询参数传递,不需要把整个Criteria对象序列化成单个字符串:

  • 分页参数正常传递page、pageSize,也可以直接用Spring Data的Pageable对象统一接收
  • 筛选规则直接按字段名.过滤操作=值的格式传,比如你要实现symbol字段的模糊匹配,直接传参数symbol.contains=abcdef即可
  • 接口层直接声明DocCriteria类型的入参,加上@ParameterObject注解方便Swagger识别,不需要额外加任何解析逻辑,Spring会自动把扁平参数绑定到Criteria对象的对应Filter字段上,调整后的接口示例:
@GetMapping("/")
@PageableAsQueryParam
public ResponseEntity<Page<Dto>> getAll(
        @RequestHeader("Authorization") String token,
        @org.springdoc.api.annotations.ParameterObject DocCriteria criteria,
        @ParameterObject Pageable pageable
) throws IOException {
    // 直接使用criteria即可,symbol的contains属性会自动绑定为abcdef
}

方案2:调用方逻辑无法修改,必须传toString格式的criteria字符串时,自定义解析逻辑

如果调用方已经写死了传DocCriteria(id=null, symbol=StringFilter [contains=abcdef, ])格式的单字符串参数,就自己实现格式解析:

  • 最省事的接入方式是先保留接口入参为String criteria,拿到字符串后手动解析成DocCriteria对象再使用
  • 如果想做全局自动绑定,可以实现Spring的Converter<String, DocCriteria>接口,把解析逻辑注册到Spring类型转换服务,之后接口直接声明DocCriteria criteria入参就能自动转换

针对你当前场景的简易解析逻辑示例(可根据自己的字段扩展):

private DocCriteria parseCriteria(String criteriaStr) {
    DocCriteria criteria = new DocCriteria();
    // 剥掉外层类名包裹的括号
    String content = criteriaStr.substring(criteriaStr.indexOf("(") + 1, criteriaStr.lastIndexOf(")"));
    // 拆分顶级字段
    String[] fieldPairs = content.split(", ");
    for (String pair : fieldPairs) {
        String[] kv = pair.split("=", 2);
        String field = kv[0].trim();
        String value = kv[1].trim();
        if ("symbol".equals(field) && !"null".equals(value)) {
            StringFilter stringFilter = new StringFilter();
            // 解析StringFilter里的contains规则
            if (value.contains("contains=")) {
                int containStart = value.indexOf("contains=") + 9;
                int containEnd = value.indexOf(",", containStart);
                stringFilter.setContains(value.substring(containStart, containEnd).trim());
            }
            criteria.setSymbol(stringFilter);
        } else if ("id".equals(field) && !"null".equals(value)) {
            LongFilter longFilter = new LongFilter();
            // 按照LongFilter的toString格式补充对应解析逻辑即可
            criteria.setId(longFilter);
        }
        // 其他Criteria字段按相同规则扩展
    }
    return criteria;
}

你之前手动调用ObjectMapper报错的原因很简单:你传入的待转换对象是个普通字符串,Jackson会尝试找一个接收单个String参数的构造方法来创建DocCriteria实例,你没有提供这种构造方法,自然会抛异常。就算你加了这个构造方法,也得在构造方法里写上面的解析逻辑,Jackson本身没有内置解析这种Java toString文本的能力。

最后提个注意点:不要尝试写通用的toString格式解析器,这种格式本身没有统一规范,一旦字段值里包含逗号、括号这类特殊字符,拆分逻辑很容易出问题,能调整调用方传参格式就优先选方案1,稳定性最高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 07:39:19