【问题标题】:Regex To Parse Strings To Map正则表达式解析字符串以映射
【发布时间】:2021-01-19 02:41:45
【问题描述】:

我有以下字符串,我想将其解析为可以包含字符串和整数值的 Map 的 Map。字符串包含一个键,该键可以由字母、空格和/或特殊字符和值(另一个映射)组成,位于一些花括号 “{““}” 内:

    {A->B={A=0, C=2, B=3, D=“A”, M=0, H=7, key=A->B},
     B->C={A=0, C=2, B=3, D=“A”, M=0, H=7, key=B->C}, 
     D & E={A=0, C=2, B=4, D=“A”, M=0, H=7, key=D & E},
     FGH={A=0, C=2, B=3, D=“A”, M=0, H=7, key=FGH}}

我需要一个正则表达式来识别花括号内的键/值,以便我可以在使用内部映射的键将映射存储到另一个外部映射之前将它们解析为映射。

到目前为止,这是我的代码:

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StringToMapOfMapsDemo {

    public static void main(String[] args) {

        String str = "{A->B={A=0, C=2, B=3, D=“A”, M=0, H=7, key=A->B},
                              B->C={A=0, C=2, B=3, D=“A”, M=0, H=7, key=B->C}, 
                              D & E={A=0, C=2, B=4, D=“A”, M=0, H=7, key=D & E},
                              FGH={A=0, C=2, B=3, D=“A”, M=0, H=7, key=FGH}}";
        List<String> stringList = Stream.of(str.split("\\s*[{},]\\s*")).map(String::trim).collect(Collectors.toList());
        System.out.println(stringList);
        Map<String, Object> outerMap = new HashMap<>();
        for (String keyValue : stringList) {
            System.out.println(keyValue);
            Map<String, String> innerMap = new HashMap<>();
            String[] keyValueParts = keyValue.split("=");
            System.out.println(keyValueParts);
            innerMap.put(keyValueParts[0], keyValueParts[1]);
            if (innerMap.containsKey("key")){
                String keyForOuterMap = innerMap.get("key");
                outerMap.put(keyForOuterMap, innerMap);
            }
        }
        System.out.println(outerMap);
    }
}

【问题讨论】:

    标签: java json regex


    【解决方案1】:

    帮不了你,因为你首先要split(),它消耗分隔符,通过环视来匹配使用这个正则表达式的键:

    [^{}=,\s][^{}=,]+(?==\{)
    

    live demo

    我不会重新发明轮子,而是首先通过在适当的位置添加 " 将输入转换为 JSON,然后使用您想要的任何库将其解析为 Map&lt;String, Object&gt;,这些库都可以处理嵌套映射和键/带有引号的值(您需要转义)。

    这里有一些代码可以做到这一点(经过测试并使用有问题的示例输入):

    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.SerializationFeature;
    
    str = str.trim().replace("\"", "\\\""); // trim, escape quotes
    str = str.replaceAll("([{,])\\s*(.*?)=", "$1\"$2\"="); // quote names
    str = str.replaceAll("=\\s*(?!\\{)(.*?)([},])", "=\"$1\"$2"); // quote values
    str = str.replace('=', ':'); // replace = with :
    // str is now valid json
    
    // parse, chosing the jackson library
    ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); // with pretty option
    // parse, deserialize to LinkedHashMap to preserve order
    Map<String, Object> map = (HashMap<String, Object>) mapper.readValue(str, LinkedHashMap.class);
    // print parsed map as correctly indented json (see INDENT_OUTPUT enabled above)
    System.out.println(mapper.writeValueAsString(map));
    

    如果您坚持编写自己的代码,则需要编写一个能够理解您的语言语法的适当解析器。正则表达式可能会对此有所帮助,但您还需要将输入标记为 AST 的复杂逻辑。相反,我会按照上面的简单方法来做。

    【讨论】:

    • 关于如何轻松将输入转换为 JSON 以便我可以使用 objectMapper 解析它的任何建议?
    • @Orby 查看额外答案。
    猜你喜欢
    • 1970-01-01
    • 2016-04-29
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多