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

Java如何从指定表单字符串中提取目标键值对数据

问题说明

你需要解析一段存在键值对拼接、空值冗余问题的表单提交字符串,原始字符串定义如下:

String tmp = "Reason: decision=deny&denyReason=1&denyReasonSubcategory=PoorQuality&subCategoryComments=testsubCategoryComments=subCategoryComments=denyReasonSubcategory=ReviewAgainsubCategoryComments=hellosubCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryCommen=&subCategoryComments=&subCategoryComments=&subCategoryComments=&subCategoryComments=";

提取目标:

  1. 提取所有denyReason的值存入数组,方便查询
  2. 提取denyReasonSubcategory和对应非空subCategoryComments的配对,最终输出格式为PoorQuality:test; ReviewAgain:hello

你之前的实现存在三个明显问题,导致无法拿到正确结果:

  • 键名拼写错误:代码中写的是declineReason,和原始字符串的denyReason拼写不匹配
  • 分割逻辑错误:仅按&分割字符串,无法处理原始串中多个键值对直接拼接、无&分隔的长片段
  • 缺少配对逻辑:仅判断键是否存在,没有建立子分类和对应评论的关联关系,也没有过滤大量空值的冗余字段
实现方案

核心思路是用正则全局匹配所有合法的键=值片段,不依赖&做分割,匹配时自动截断到下一个键名/&/字符串末尾,过滤空值后按业务逻辑做配对存储。
完整可运行代码如下:

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FormStringParser {
    public static void main(String[] args) {
        String tmp = "Reason: decision=deny&denyReason=1&denyReasonSubcategory=PoorQuality&subCategoryComments=testsubCategoryComments=subCategoryComments=denyReasonSubcategory=ReviewAgainsubCategoryComments=hellosubCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryComments=subCategoryCommen=&subCategoryComments=&subCategoryComments=&subCategoryComments=&subCategoryComments=";

        // 存储denyReason值的列表,支持多值查询
        List<String> denyReasons = new ArrayList<>();
        // 存储子分类和对应评论的配对,LinkedHashMap保证插入顺序
        Map<String, String> subCategoryCommentMap = new LinkedHashMap<>();

        // 正则规则:匹配三个目标键,捕获对应的值,遇到下一个键/&/字符串结尾就停止值匹配
        Pattern kvPattern = Pattern.compile("(denyReason|denyReasonSubcategory|subCategoryComments)=([^&]*?)(?=(denyReason|denyReasonSubcategory|subCategoryComments)=|&|$)");
        Matcher matcher = kvPattern.matcher(tmp);

        String currentMatchedSubCategory = null;
        while (matcher.find()) {
            String key = matcher.group(1);
            String value = matcher.group(2);
            // 跳过空值
            if (value.isBlank()) {
                continue;
            }
            switch (key) {
                case "denyReason":
                    denyReasons.add(value);
                    break;
                case "denyReasonSubcategory":
                    currentMatchedSubCategory = value;
                    break;
                case "subCategoryComments":
                    // 只给最近匹配到的、还未绑定评论的子分类配对
                    if (currentMatchedSubCategory != null) {
                        subCategoryCommentMap.put(currentMatchedSubCategory, value);
                        currentMatchedSubCategory = null;
                    }
                    break;
            }
        }

        // 验证输出
        System.out.println("denyReason存储结果:" + denyReasons);
        // 拼接要求的格式字符串
        StringBuilder formatResult = new StringBuilder();
        for (Map.Entry<String, String> entry : subCategoryCommentMap.entrySet()) {
            if (formatResult.length() > 0) {
                formatResult.append("; ");
            }
            formatResult.append(entry.getKey()).append(":").append(entry.getValue());
        }
        System.out.println("配对数据格式化结果:" + formatResult);
    }
}

运行输出:

denyReason存储结果:[1]
配对数据格式化结果:PoorQuality:test; ReviewAgain:hello

方案适配点说明:

  • 不依赖&做分割,能正确识别所有拼接在一起的键值对,解决原始串格式不规范的问题
  • 自动过滤所有空值的冗余subCategoryComments字段,不会存入无效数据
  • 配对逻辑保证每个子分类只绑定后面紧跟的第一个非空评论,不会被后续空字段覆盖
  • denyReason用List存储,支持多值场景,直接按索引即可查询对应值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:00:53