noear / snack3 Goto Github PK
View Code? Open in Web Editor NEWHigh-performance Jsonpath framework
License: Apache License 2.0
High-performance Jsonpath framework
License: Apache License 2.0
JDK 18之后,JDK的默认编码由 uft16 => utf8,且默认都带了vector
下面是一个验证
https://github.com/AugustNagro/utf8.java 该使用了 验证utf8字符性能 在 i7-4930mx上可以跑出2.4GB/secs
Throughput for twitter.json
:
simdjson 就是使用了simd才达到了java的json库15倍以上的性能
new String(buf, UTF_8) |
Utf8.validate(buf, new LookupTables256()) |
simdjson::validate_utf8(str, len) |
---|---|---|
.8 GB/sec | 3.52 GB/sec | 24 GB/sec |
The JDK algorithm is very optimized, and uses intrinsics to check negatives (for the ASCII shortcut) and to elide array bound checks.
In the vectorized algorithm, 256 bit vectors currently perform best. We cannot go smaller than 128 bit, since nibbles (4 bits) are used to select from the lookup tables.
且 fastjson已经有一个使用jdk vector impove performance的特性,下次跑benchmark的时候,使用fastjson2 请使用 JDK>=17 (并启用该特性)
https://github.com/alibaba/fastjson2/tree/a7134cc6416f4a91662c6b37c6591c624d0e3d4d/incubator-vector
['' (, '')] | 表示一个或多个子节点
ONode n = ONode.load("{code:1,msg:'Hello world!',data:[{a:'b',c:'d'}]}");
这种写法可以正常获取到值
System.out.println(n.select("$.data[*].a"));
以下两种写法获取不到值
System.out.println(n.select("$.data[]['a']"));
System.out.println(n.select("$.data[]['a','c']"));
如题
{
"a":[
{
"b":1,
"c":2
},
{
"b":11,
"c":12
}
]
},
想映射成为下面的数组
{
"saa": [
{
"sb":1,
"sc":2
},
{
"sb":11,
"sc":12
}
]
}
举个栗子:
当我有个json:{"A": {"B": 1}}
当我load(json, new Options(0)).select("$.A.B1").getString()
查询出来的结果一直是“”,而不是null ,尽管我额外设置了Options【后面这个Options被忽略掉了】,跟踪下来看到:
/**
* 执行jpath指令
*/
private static ONode exec(JsonPath jsonPath, ONode source, boolean useStandard) {
ONode tmp = source;
boolean branch_do = false;
for (Segment s : jsonPath.segments) {
if (tmp == null) {//多次转换后,可能为null
break;
}
if (branch_do && (useStandard || s.cmdAry != null)) { //..a[x] 下属进行分支处理 //s.cmdAry != null
ONode tmp2 = new ONode().asArray();
Consumer<ONode> act1 = (n1) -> {
ONode n2 = s.handler.run(s, source, n1, useStandard);
if (n2 != null) {
if (s.cmdAry != null) {
if (n2.isArray()) {
tmp2.addAll(n2.ary());
} else {
tmp2.addNode(n2);
}
} else {
tmp2.addNode(n2);
}
}
};
tmp.ary().forEach(act1);
tmp = tmp2;
if (useStandard == false) {
branch_do = false;
}
} else {
tmp = s.handler.run(s, source, tmp, useStandard);
branch_do = s.cmdHasUnline;
}
}
if (tmp == null) {
return new ONode(); // 问题在这里,为什么要忽略设置Options而使用默认构造的?
} else {
return tmp;
}
}
想问下,这里在new ONode时可否将“ONode source” 的options设置到新ONode中,而非使用默认的,因为我这里就是不想使用使用Feature.StringNullAsEmpty。
如何支持对象被循环引用的序列化和反序列化。
XmlFromer 和YamlFromer 这两个数据我并没有在项目里面找到他,作者能回答一下这玩意到底有没有么,我觉得xml到json的转换还是挺不错的
相比JsonPath,这个库少了很多好用的function,比如length(), concat(), index()等等。
这是A类
package test;
public class A {
private B b;
public A(B b) {
this.b = b;
}
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
这是B类
package test;
import java.util.List;
public class B {
private List<String> bList;
public B(List<String> bList) {
this.bList = bList;
}
public List<String> getbList() {
return bList;
}
public void setbList(List<String> bList) {
this.bList = bList;
}
}
这是单元测试
@Test
public void test6(){
String poc = "{\"@type\":\"test.A\"," +
"\"b\":{\"@type\":\"test.B\",\"bList\":\"str1\"}}";
System.out.println(poc);
A o = ONode.deserialize(poc);
System.out.println(o.getB().getbList().size());
}
程序输出结果
{"@type":"test.A","b":{"@type":"test.B","bList":"str1"}}
3
预期应该是1而不是3
@Data
public class A {
private List<String> names;
}
public class Test {
public static void main(String[] args) {
String json = "{\"names\":null}";
A a = ONode.loadStr(json).toObject(A.class);
System.out.println(a);
System.out.println(ONode.load(a).toJson());
}
}
结果:
A(names=[null])
{"names":[null]}
//测试代码
String test = """
{
"1": {
"a1": [{"id":"a1"},{"id":"a2"}],
"b1": [{"id":"b1"},{"id":"b2"}]
},
"2": {
"a2": [{"id":"a1", "id1":"a11", "userId": "a12"},{"id":"a2"}],
"b2": [{"id":"b1"},{"id":"b2"}]
}
}
""";
String jsonPath = "$...*";
System.out.println("org.noear.snack: " + ONode.load(test).select(jsonPath).toJson());
//期望结果:
[{"id":"a1"},{"id":"a2"},{"id":"b1"},{"id":"b2"},{"id":"a1","id1":"a11","userId":"a12"},{"id":"a2"},{"id":"b1"},{"id":"b2"}]
//目前实际测试结果:
[{"a1":[{"id":"a1"},{"id":"a2"}],"b1":[{"id":"b1"},{"id":"b2"}]},{"a2":[{"id":"a1","id1":"a11","userId":"a12"},{"id":"a2"}],"b2":[{"id":"b1"},{"id":"b2"}]}]
@Test
void testGet() {
ONode root = ONode.load(new HashMap<>());
ONode data = root.get("data");
data.set("b", "2222");
System.out.println(root);
}
v3.1.14 正常输出:
{"data":{"b":"2222"}}
v3.2.22 输出异常,根目录没有数据:
{}
ONode.getOrNew(String key)
当key包含数组下标时,会无法正确解析,比如a[0]
对数组中的json对象字段进行判读过滤符合条件的JSON对象
举个栗子🌰:
数组JSON
[
{"id": 0, "payAmount":5.0, "payTime": "2022-10-10 12:00:00"},
{"id": 1, "payAmount":100, "payTime": "2022-10-10 12:00:00"},
{"id": 2, "payAmount":20, "payTime": "2023-10-10 12:00:00"},
{"id": 3, "payAmount":50, "payTime": "2023-11-11 00:00:00"}
]
如我想获取某年【2023】的销售金额最大的那条记录, 那么2023年销售金额最大的JSON就是{"id": 3, "payAmount":50, "payTime": "2023-11-11 00:00:00"}
我现在有一个场景是需要先将值取出来,然后把它转换成我需要的,再放在之前的json位置中,如果用jsonPath就可以用DocumentContext,然后通过jsonPath直接set值,但是用ONode我发现,在set的时候,我需要用到key值。所以在这个时候我要怎么获取到这个node的key值,或者这个问题有更好的解决方案吗。感谢!
//先将要改动的拿出来,然后把值改为空,把后来改完的node加进去,最后进行一轮判空输出 ONode o = ONode.loadStr(json); ONode childNode = o.select(jsonPath); String bizValue = o.select(jsonPath).getString(); //将原来的值改为空 o.select(jsonPath).asNull(); //操作原来的值做转换,拿到操作完的值 String convertResult = operateData(ruleCode, mappingCode, bizValue); childNode.val(convertResult); //最后怎么将o中的这个节点的值替换掉
@Test
public void testONodeToJson() {
String jsonSomeFieldValueContainBackslash = "{\"abc\":\"\\abc\"}";
ONode oNode = ONode.loadStr(jsonSomeFieldValueContainBackslash);
String toJson = oNode.toJson();
assertEquals(jsonSomeFieldValueContainBackslash, toJson, "json ne toJson!");
}
测试结果为:
org.opentest4j.AssertionFailedError: json ne toJson! ==>
Expected :{"abc":"\abc"}
Actual :{"abc":"\\abc"}
结果会多出一个\
您好,作者。
我正在使用3.1.5.9
版本的snack3
,现有这样的需求,通过传入参数的jsonpath,定位到json指定的位置,然后对该指定路径的json值进行修改。
之前使用的 com.jayway.jsonpath.JsonPath
,是这样实现的
` // JsonPath的配置信息
Configuration conf = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL, Option.SUPPRESS_EXCEPTIONS);
// 指定配置信息,获取json上下文对象
DocumentContext context = JsonPath.using(conf).parse(rawJsonStr);
// 预编译JsonPath
JsonPath path = JsonPath.compile(jsonPathStr);
// 在指定的path节点上,设置新值
try {
context.set(path, newValue);
}
// 路径找不到时,抛出异常
catch (PathNotFoundException e) {
throw new RuntimeException("JasonPath:" + jsonPathStr + " not found.", e);
}
// 获取新的json字符串
String newJsonStr = context.jsonString();
`
但因为com.jayway.jsonpath.JsonPath
的性能问题,想将类库替换为snack3,想麻烦大佬看看snack3下,如何实现上述需求。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.