自己动手写json解析器0x02-分词清洗

介绍

在上一节中,我们介绍了如何对json进行分词,并且成功对示例json进行了分词,这一节我们介绍如何对分词进行清洗,可能清洗这个词用的不是很准确,但是我也不知道专业叫法叫啥,有知道的同学希望在评论区留言,分词清洗的目的就是将tokens进行整理,去掉一些没用的,然后进行一些整合便于后续的分析,有点像大数据里的数据清洗将脏数据清洗为能被业务所用的高质量数据,所以这里用了分词清洗这个词。

分词清洗

介绍

为了便于后面步骤的处理,我们这里需要对分词进行清洗,清洗后的分词列表可以满足以下要求

  • 第一节中字符串都是当作type=string处理,经过清洗后,可以区分key和value
  • 如果完成了key-value的清洗,那么kvSymbol就不需要了,后续也不需要用到这个token,可以从列表中移除

实现

以下是具体实现的代码

/**
 * token清洗
 * 区分key和value的token
 *
 * @param originTokens 原始token列表
 * @return 清洗过的token列表
 */
public List tokenClean(List originTokens) {
    jsonTokens = new ArrayList<>();
    int tokenIndex = 0;
    while (tokenIndex < originTokens.size()) {
        Token token = originTokens.get(tokenIndex);
        if ("string".equals(token.getType())) {
            if (tokenIndex + 1 < originTokens.size() &&
                    "kvSymbol".equals(originTokens.get(tokenIndex + 1).getType())) {
                token.setType("key");
                jsonTokens.add(token);
                Token valueToken = originTokens.get(tokenIndex + 2);
                //object和array类型暂时不设置value类型
                if (!"object".equals(valueToken.getType()) && !"array".equals(valueToken.getType())) {
                    valueToken.setType("value");
                }
                jsonTokens.add(valueToken);
                //因为读取了kvSymbol和value两个token因此要+2
                tokenIndex += 2;
            } else {
                //如果没有kvSymbol直接当作value进行处理
                token.setType("value");
                jsonTokens.add(token);
            }
        } else {
            //清洗目前只处理string类型其他类型忽略
            jsonTokens.add(token);
        }
        ++tokenIndex;
    }
    return jsonTokens;
}

测试

我们使用示例json进行测试

public class Main {

    public static void main(String[] args) throws Exception {
        InputStream fin = Main.class.getResourceAsStream("/example.json");
        byte[] buf = new byte[fin.available()];
        fin.read(buf);
        fin.close();
        String json = new String(buf, "utf-8");
        JSONParser parser = new JSONParser();
        List tokens = parser.tokenizer(json);
        tokens = parser.tokenClean(tokens);
        System.out.println(String.format("|%-12s|%-12s|%-15s|", "type", "valueType", "value"));
        System.out.println("-------------------------------------------");
        for (Token t : tokens) {
            System.out.println(String.format("|%-12s|%-12s|%-15s|",
                    t.getType(),
                    t.getValueType(),
                    t.getValue()));
        }
        System.out.println("-------------------------------------------");
    }
}

结果如下:

|type        |valueType   |value          |
-------------------------------------------
|object      |object      |{              |
|key         |string      |name           |
|value       |string      |asan           |
|key         |string      |age            |
|value       |long        |32             |
|key         |string      |married        |
|value       |bool        |true           |
|key         |string      |birthday       |
|value       |string      |1992-02-08     |
|key         |string      |salary         |
|value       |float       |1234.56        |
|key         |string      |description    |
|value       |string      |a "hudsom" man |
|key         |string      |tags           |
|array       |array       |[              |
|value       |string      |coder          |
|value       |string      |mid-age        |
|array       |array       |]              |
|key         |string      |location       |
|object      |object      |{              |
|key         |string      |province       |
|value       |string      |福建省          |
|key         |string      |city           |
|value       |string      |泉州市          |
|key         |string      |area           |
|value       |string      |晋江市          |
|object      |object      |}              |
|key         |string      |family         |
|array       |array       |[              |
|object      |object      |{              |
|key         |string      |relation       |
|value       |string      |couple         |
|key         |string      |name           |
|value       |string      |Helen          |
|object      |object      |}              |
|object      |object      |{              |
|key         |string      |relation       |
|value       |string      |daughter       |
|key         |string      |name           |
|value       |string      |XiaoMan        |
|object      |object      |}              |
|array       |array       |]              |
|object      |object      |}              |
-------------------------------------------

和清洗前相比,没有了kvSymbol并且成功区分了key和value类型

代码

完整代码请参考项目https://github.com/wls1036/tiny-json-parser的0x02分支

你可能感兴趣的:(解析器编译器)