繁体   English   中英

Java:如何将此字符串转换为ArrayList?

[英]java: how to convert this string to ArrayList?

String text = '[["item1","item2","item3"], ["some", "item"], ["far", "out", "string"]]';

我想遍历每个单独的ArrayList。 我不知道如何将字符串转换为适当的ArrayList对象。

这种语法看起来像是JSON的子集,我猜想客户端实际上是将其编码为JSON。 假设这是真的,最简单的方法将是使用现成的JSON解析器和一些简单的Java代码将生成的对象转换为代码所需的形式。

当然,您可以手动实现自己的解析器,但是这样做可能不值得,特别是如果您必须处理字符串转义,空格中的可变性等问题时。 不要忘记,如果您实现自己的解析器,则需要实施单元测试以确保它可以在预期的有效输入的全部范围内工作,也可以对无效的输入工作。 (测试无效输入的情况很重要,因为如果某些黑客发送包含错误输入的请求,您不希望服务器崩溃。)

在继续之前,您确实需要确认客户端向您发送的确切语法。 仅看一个例子并不能回答这个问题。 您或者需要一个文档来指定语法是什么,或者您需要查看客户端/应用程序的源代码。

这是一个简单的解析器,它应该处理各种滥用嵌套,并且对单引号和双引号具有鲁棒性,但是它并不关心是否将'test"等同于"test"对待。

编辑:添加了注释,现在它处理字符串中的转义引号。 (现在进一步改进了字符串令牌处理)

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

public class StringToList {

    public static void main(String[] args) throws IOException{
        StringReader sr = new StringReader("[[\"it\\\"em1\", \"item2\",\"item3\"], [\"some\",\"item\"], [\"far\",\"out\",\"string\"]]");
        System.out.println(tokenize(sr));
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static List tokenize(StringReader in) throws IOException{
        List stack = new ArrayList<Object>();
        int c;
        while((c = in.read()) != -1){
            switch(c){
            case '[':
                // found a nested structure, recurse..
                stack.add(tokenize(in));
                break;
            case ']':
                // found the end of this run, return the
                // current stack
                return stack;
            case '"':
            case '\'':
                // get the next full string token
                stack.add(stringToken(in));
                break;
            }
        }

        // we artificially start with a list, though in principle I'm
        // defining the string to hold only a single list, so this
        // gets rid of the one I created artifically.
        return (List)stack.get(0);
    }

    public static String stringToken(StringReader in) throws IOException{
        StringBuilder str = new StringBuilder();
        boolean escaped = false;
        int c;
        outer: while((c = in.read()) != -1){
            switch(c){
            case '\\':
                escaped = true;
                break;
            case '"':
            case '\'':
                if(escaped){
                    escaped = false;
                }else{
                    break outer;
                }
            default:
                str.append((char)c);
            }
        }
        return str.toString();
    }

}

请注意以下几点:这不会使您的语法正确,因此,如果您对引号进行愚蠢的操作(如我所描述的那样),它可能仍会被解析为(意外)预期。 另外,我没有人强制逗号,你甚至不需要引号之间的空间,所以["item1""item2"]就是采用这种解析器是有效的["item1", "item2"]但也许更奇怪的是,这个东西也应该处理["item1"asdf"item2"]而忽略asdf

由于您使用的是看起来像JSON的字符串,因此我只会使用JSON解析器。 使用最简单的方法之一是gson。 这是使用gson的示例:

String text = '[["item1","item2","item3"], ["some", "item"], ["far", "out", "string"]]';
GSON gson = new GSON();
ArrayList<ArrayList<String>> list = gson.fromJson(text, new TypeToken<ArrayList<ArrayList<String>>>() {}.getType());

这是gson网站: http : //code.google.com/p/google-gson/

您需要手动构建一个解析器。 这并不难,但是会占用时间。 在前面的评论中,您说过要ArrayList的ArrayList ... hmmm ...好

只需按char解析字符串char并通过首先定义递归解析规则即可识别每个标记。 递归后代解析器规则通常是图形化的,但是我可以尝试为您使用ABNF

LIST = NIL / LIST_ITEM *( ',' SP LIST_ITEM)
LIST_ITEM = NIL / '[' STRING_ITEM *(, SP STRING ITEM) ']'
STRING_ITEM = '"' ANYCHAR '"'
SP = space
ANYCHAR = you know, anything that is not double quotes
NIL = ''

另一种方法是使用正则表达式。 这是几个示例。 首先通过捕获外部元素

(\[[^\]]*\])

上面的正则表达式捕获了从'['到第一个']'的所有内容,但是您需要对其进行修改或从字符串中删除方括号(只需删除第一个和最后一个字符)

然后通过捕获内部元素

(\"[^\"]\")

像上面一样简单

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM