关于解析器:自己动手写json解析器0x04生成对象

35次阅读

共计 2665 个字符,预计需要花费 7 分钟才能阅读完成。

介绍

通过分词和形象语法树生成后,咱们就能够依据语法树生成 java 对象,为了让程序尽量简略,object 用 Map 返回,array 用 List<Map> 返回,根本类型间接返回 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 解析器全副的工作。

代码

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

正文完
 0