如何根据查询参数字符串填充对象?

时间:2017-01-02 14:43:35

标签: java regex url java-8

我有这样的字符串:

    //RULE countryname=Brazil&useryear<=2017&usermonth<=01&userdayofmonth<=15 200

我想填充我创建的对象:

公共阶级规则{

public List<String> countries;
public LocalDateTime fromTime;
public LocalDateTime toTime;

我使用了正则表达式,但我想知道是否有更优雅的方法可以这样做?

@Test
public void testRegex() throws Exception {
    Pattern pattern = Pattern.compile(".*?flag\\((\\d+)\\)=true(.*)");
    Matcher matcher = pattern.matcher("bbbbbbflag(27)=true 300");
    while (matcher.find()) {
        System.out.println("group 1: " + matcher.group(1));
    }

    pattern = Pattern.compile("(.*?)countryname=([\\w-]+)(.*)");
    matcher = pattern.matcher("countryname=brazil  ");
    while (matcher.find()) {
        System.out.println("group 2: " + matcher.group(2));
    }

    pattern = Pattern.compile(".*?countryname=(.*+)&.*]");
    matcher = pattern.matcher("countryname=brazil&bllllll");
    while (matcher.find()) {
        System.out.println("group 1: " + matcher.group(1));
    }

    pattern = Pattern.compile(".*?useryear<=(\\d+)&usermonth<=(\\d+)&userdayofmonth<=(\\d+)(.*)");
    matcher = pattern.matcher("useryear<=2017&usermonth<=01&userdayofmonth<=15");
    while (matcher.find()) {
        System.out.println("group 1: " + matcher.group(1));
        System.out.println("group 2: " + matcher.group(2));
        System.out.println("group 3: " + matcher.group(3));
    }
}

2 个答案:

答案 0 :(得分:0)

您可以将模式与|合并,然后查找所有匹配项:

String s = "//RULE countryname=Brazil&useryear<=2017&usermonth<=01&userdayofmonth<=15 200\n";
Pattern p = Pattern.compile("((countryname)=([\\w-]+)|(useryear)<=(\\d+)|(usermonth)<=(\\d+)|(userdayofmonth)<=(\\d+))");
Matcher m = p.matcher(s);

while(m.find()){
    String type = "";
    String value = "";
    boolean first = true;

    for(int i = 2; i<=m.groupCount(); i++){
        String group = m.group(i);
        if(first && group != null){
            type = group;
            first = false;
        }else if(group != null){
            value = group;
            break;
        }
    }

    System.out.println("Type: " + type + " Value: " + value);
}

输出:

Type: countryname Value: Brazil
Type: useryear Value: 2017
Type: usermonth Value: 01
Type: userdayofmonth Value: 15

答案 1 :(得分:0)

你可以在没有正则表达式的情况下完成。由于您的字符串类似于带参数的http查询,因此我们可以采用与http查询类似的方式对其进行解析。请尝试此示例可以帮助您。

package gnu;

import java.util.*;
import java.util.stream.Collectors;
import java.util.AbstractMap.SimpleImmutableEntry;
import static java.util.stream.Collectors.toList;

public class Main {

    public static void main(String[] strg) {

        String str = "//RULE countryname=Brazil&useryear<=2017&usermonth<=01&userdayofmonth<=15 200";
        str = str.substring(str.indexOf(" ")+1, str.lastIndexOf(" "));
        try {
            ParseParams parse = new ParseParams();
            Map<String, List<String>> map = parse.parseParams(str);
            map.entrySet().forEach(entry -> {
                System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
            });
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

class ParseParams {

    Map<String, List<String>> parseParams(String url) {

        return Arrays.stream(url.split("&"))
                .map(this::splitQueryParameter)
                .collect(Collectors.groupingBy(SimpleImmutableEntry::getKey, LinkedHashMap::new, Collectors.mapping(Map.Entry::getValue, toList())));
    }

    private SimpleImmutableEntry<String, String> splitQueryParameter(String it) {
        final int idx = it.indexOf("=");
        String key = idx > 0 ? it.substring(0, idx) : it;
        String value = idx > 0 && it.length() > idx + 1 ? it.substring(idx + 1) : null;
        if (key.contains("<")) {
            key = key.replace("<", "");
        }
        return new SimpleImmutableEntry<>(key, value);
    }
}

输出

Key : countryname Value : [Brazil]
Key : useryear Value : [2017]
Key : usermonth Value : [01]
Key : userdayofmonth Value : [15]

Online demo.