自己动手写json解析器0x04-生成对象

165 阅读1分钟

介绍

经过分词和抽象语法树生成后,我们就可以根据语法树生成java对象,为了让程序尽量简单,object用Map返回,array用List返回,基本类型直接返回value

实现

语法树到对象的生成相对还是比较简单,首先我们定义了一个总的入口函数

/**
 * 将json生成java对象
 *
 * @param item
 * @return
 */
public Object generate(Ast item) {
    if ("array".equals(item.getType())) {
        //返回数组对象
        return generateList(item);
    } else if ("object".equals(item.getType())) {
        //返回object对象
        return generateObject(item);
    } else if ("value".equals(item.getType())) {
        //基本类型json对象,比如"100"也是一个json对象
        return item.getValue();
    }
    return null;
}

对应三种类型的处理方式

generateObject

/**
 * 生成object对象
 *
 * @param astItem
 * @return
 */
public Map generateObject(Ast astItem) {
    //object对象以Map形式返回
    Map<String, Object> object = new HashMap<>();
    for (Ast ast : astItem.getItems()) {
        Object value = null;
        if ("object".equals(ast.getType()) || "array".equals(ast.getType())) {
            value = generate(ast);
        } else if ("value".equals(ast.getType())) {
            value = ast.getValue();
        }
        object.put(ast.getName(), value);
    }
    return object;
}
  • 遍历object的字段
  • 如果是object或者array,那么通过入口函数进行递归
  • 如果是value直接取value值就行

generateList

/**
 * 生成object对象数组
 *
 * @param item
 * @return
 */
public List<Object> generateList(Ast item) {
    //数组对象以List<Object>形式返回
    List<Object> result = new ArrayList<>();
    for (Ast child : item.getItems()) {
        if ("object".equals(child.getType())) {
            result.add(generateObject(child));
        } else if ("value".equals(child.getType())) {
            result.add(child.getValue());
        } else if ("array".equals(child.getType())) {
            result.add(generateList(child));
        }
    }
    return result;
}
  • 遍历数组列表
  • 如果是object进入对象处理函数
  • 如果是value直接取值
  • 如果是array递归进入数组处理函数

测试

我们将生成的对象重新用fastjson变成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<Token> tokens = parser.tokenizer(json);
        tokens = parser.tokenClean(tokens);
        List<Ast> astItems = parser.generateAST();
        Ast ast = astItems.get(0);
        Object object = parser.generate(ast);
        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("-------------------------------------------");
        System.out.println(JSON.toJSONString(ast, true));
        System.out.println(JSON.toJSONString(object, true));
    }
}

结果

{
	"birthday":"1992-02-08",
	"name":"asan",
	"description":"a \"hudsom\" man",
	"location":{
		"area":"晋江市",
		"province":"福建省",
		"city":"泉州市"
	},
	"salary":1234.56,
	"family":[
		{
			"name":"Helen",
			"relation":"couple"
		},
		{
			"name":"XiaoMan",
			"relation":"daughter"
		}
	],
	"married":true,
	"age":32,
	"tags":[
		"coder",
		"mid-age"
	]
}

除了字段顺序外其他数据都和原始的示例json一样,说明结果是正确的,至此我们完成了一个json解析器全部的工作。

代码

完整代码请参考项目github.com/wls1036/tin…的0x04分支