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

介绍

经过分词和抽象语法树生成后,我们就可以根据语法树生成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 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 generateList(Ast item) {
    //数组对象以List形式返回
    List 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 tokens = parser.tokenizer(json);
        tokens = parser.tokenClean(tokens);
        List 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解析器全部的工作。

代码

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

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