不是已经有 objectMapper.readValue 了吗?为什么还需要一个新的 JSON 库呢?因为我发现下面这几个场合已有的库无法满足我的需求, 所以发明了 jsoniter(json-iterator):和 PHP 打交道: 如果你要的是 int,他们可能给你 100 也可能给你 "100"。如果你要的是对象,他们在空值的时候可能给你个 []。
处理大量的 JSON:解析大量的 JSON,但是只是从中提取少量的信息
无法直接绑定到对象上:JSON自身是 key/value 的形式,和对象模型没法直接绑定上
除了灵活之外 jsoniter 还比现有的库快很多(比如 jackson,gson,fastjson 这些),欢迎第三方来做公正客观的性能评测。这是我自测 1kb json 数据绑定的结果:
jsoniter 的独特之处源自创新:jsoniter使用 tri-tree 的方式来提高性能。
jsoniter使用动态代码生成来实现 class shadowing,从而实现无损的切换。
虽然做了很多工作来确保 jsoniter是最快的。但是大部分人其实只要有一个东西能帮他们把事情搞定就好了。来一个例子展示 api 是多么的灵活,也许更有意义:
[1024, {"product_id": 100, "start": "beijing"}]
["1025", {"product_id": 101, "start": "shanghai"}]
// many many more lines
每行是代表一个订单。第一个元素是订单id,第二个元素是订单详情。值得注意之处有以下几点:行数可能很多,一次性读进来内存压力很大
某些行的订单id是 int,某些行的订单id是 string。这在和 PHP 交互的时候经常发生。
订单详情有很多字段,手工读取很麻烦,需要对象绑定
只需要 6 行代码,以上所有问题都可以解决:
JsonIterator iter = JsonIterator.parse(input); // input streamOrderDetails orderDetails = new OrderDetails(); // reusedwhile(iter.whatIsNext() != ValueType.INVALID) {
Any order = iter.readAny(); // lazy int orderId = order.toInt(0); // weakly typed String start = order.get(1).bindTo(orderDetails).start; // data binding}JsonIterator.parse 以 InputStream 作为输入,所有解析都是流式处理的
readAny 返回了 Any 类型的对象。实际的解析只有在取成员字段的时候才发生。用起来简单,而且速度快。
bindTo(orderDetails),不仅仅支持对象绑定,甚至可以绑定到已有对象上避免分配内存
jsoniter 在普通的序列化,反序列化的场景下也很好使,就一行。
JsonStream.serialize(new int[]{1,2,3})
JsonIterator.deserialize("[1,2,3]", int[].class)
jsoniter 不强迫你使用任何一种风格,可以在数据绑定,流式解析,Any三种风格里自由混搭。虽然文档不多,但还是有一些的。还是觉得文档不够,请告诉我你的需求。
希望能引起大家的一点点兴趣。库还很新,如果有 bug 欢迎提交 bug report 和 pull request 到 json-iterator/java。jsoniter的 golang 版本会在稍后更新到和 java 版本一样的水平,甚至更好。