【发布时间】:2019-12-17 12:01:57
【问题描述】:
当标记一个 JSON 字符串时,它返回一个不正确的值,就像它一次连接多个值一样(即"username": "Azoraqua", "age": }(它应该分别是 IDENTIFIER(2 次)和 STRING_LITERAL(1 次)),请注意它确实返回age 数字作为它自己的令牌(分别为 INTEGER_LITERAL)。
我尝试了几种方法来实现正确的行为:
- 更改一些与 IDENTIFER 和 STRING_LITERAL 相关的正则表达式。
- 更改一些实际的标记化逻辑。
private static final Set<TokenData> tokenDatas = new LinkedHashSet<>();
static {
tokenDatas.add(new TokenData(Pattern.compile("^(,:)"), TokenType.TOKEN));
tokenDatas.add(new TokenData(Pattern.compile("^(\\{)"), TokenType.BEGIN_OBJECT));
tokenDatas.add(new TokenData(Pattern.compile("^(})"), TokenType.END_OBJECT));
tokenDatas.add(new TokenData(Pattern.compile("^(\\[)"), TokenType.BEGIN_ARRAY));
tokenDatas.add(new TokenData(Pattern.compile("^(])"), TokenType.END_ARRAY));
tokenDatas.add(new TokenData(Pattern.compile("^(\".*\":)"), TokenType.IDENTIFIER));
tokenDatas.add(new TokenData(Pattern.compile("^(\".*\")"), TokenType.STRING_LITERAL, (s) -> s.substring(1, s.length() - 1)));
tokenDatas.add(new TokenData(Pattern.compile("^((-)?[0-9]+)"), TokenType.INTEGER_LITERAL));
tokenDatas.add(new TokenData(Pattern.compile("^((-)?[0-9]*(\\.)[0-9]+)"), TokenType.DOUBLE_LITERAL));
tokenDatas.add(new TokenData(Pattern.compile("^(true|false)", Pattern.CASE_INSENSITIVE), TokenType.BOOLEAN_LITERAL));
}
@Override
public Token next() {
str = str.trim();
if (pushback) {
pushback = false;
return lastToken;
}
if (str.isEmpty()) {
return (lastToken = new Token(TokenType.EMPTY, ""));
}
for (TokenData data: tokenDatas) {
Matcher matcher = data.pattern.matcher(str);
if (matcher.find()) {
String token = matcher.group().trim();
str = matcher.replaceFirst("");
if (data.action != null) {
token = data.action.apply(token);
}
return (lastToken = new Token(data.type, token));
}
}
throw new IllegalStateException("Could not parse " + str);
}
当输入为{"username": "Azoraqua", "age": 21} 时,输出应为:
1. BEGIN_OBJECT ({)
2.标识符("username":)
3. STRING_LITERAL ("Azoraqua")
4. 代币 (,)
5. 标识符 ("age")
6. INTEGER_LITERAL (21)
7. END_OBJECT (})
我该如何解决这个问题?
【问题讨论】: