# snack3 **Repository Path**: quickthinking/snack3 ## Basic Information - **Project Name**: snack3 - **Description**: noear::一个微型JSON框架 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 74 - **Created**: 2020-01-14 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [![Maven Central](https://img.shields.io/maven-central/v/org.noear/snack3.svg)](https://mvnrepository.com/search?q=snack3) ` QQ交流群:22200020 ` # Snack3 for java 一个微型JSON框架 基于jdk8,70kb。有序列化反序列化、解析和转换、支持 Json path 查询。 ```xml org.noear snack3 3.1.6 ``` Snack3 借鉴了 `Javascript` 所有变量由 `var` 申明,及 `Xml dom` 一切都是 `Node` 的设计。其下一切数据都以`ONode`表示,`ONode`也即 `One node` 之意,代表任何类型,也可以转换为任何类型。 * 强调文档树的操控和构建能力 * 做为中间媒体,方便不同格式互转 * 高性能`Json path`查询(兼容性和性能很赞) * 支持`序列化、反序列化` ## 随便放几个示例 ```java //demo0::字符串化 String json = ONode.stringify(user); //demo1::序列化 // -- 输出带@type String json = ONode.serialize(user); //demo2::反序列化 // -- json 有已带@type UserModel user = ONode.deserialize(json); // -- json 可以不带@type (clz 申明了) UserModel user = ONode.deserialize(json, UserModel.class); // -- json 可以不带@type,泛型方式输出(类型是已知的) List list = ONode.deserialize(json, (new ArrayList(){}).getClass()); // -- json 可以不带@type,泛型方式输出(类型是未知的) public T getObject(String json){ return ONode.deserialize(json, (new TypeRef(){}).getClass()); } //demo3::转为ONode ONode o = ONode.load(json); //将json String 转为 ONode ONode o = ONode.load(user); //将java Object 转为 ONode //demo4:构建json数据(极光推送的rest api调用) public static void push(Collection alias_ary, String text) { ONode data = new ONode().build((d)->{ d.get("platform").val("all"); d.get("audience").get("alias").addAll(alias_ary); d.get("options") .set("apns_production",false); d.get("notification").build(n->{ n.get("ios") .set("alert",text) .set("badge",0) .set("sound","happy"); }); }); String message = data.toJson(); String author = Base64Util.encode(appKey+":"+masterSecret); Map headers = new HashMap<>(); headers.put("Content-Type","application/json"); headers.put("Authorization","Basic "+author); HttpUtil.postString(apiUrl, message, headers); } //demo5:取值 o.get("name").getString(); o.get("num").getInt(); o.get("list").get(0).get("lev").getInt(); //demo5.1::取值并转换 UserModel user = o.get("user").toObject(UserModel.class); //取user节点,并转为UserModel //demo5.2::取值并填充 o.get("list2").fill("[1,2,3,4,5,5,6]"); //demo6::json path //不确定返回数量的,者会返回array类型 //找到所有的187开头的手机号,改为186,最后输出修改后的json o.select("$..mobile[?(@ =~ /^187/)]").forEach(n->n.val("186")).toJson(); //找到data.list[1]下的的mobile字段,并转为long o.select("$.data.list[1].mobile").getLong(); //查找所有手机号,并转为List List list = o.select("$..mobile").toObject(List.class); //查询data.list下的所有mobile,并转为List List list = o.select("$.data.list[*].mobile").toObject(List.class); //找到187手机号的用户,并输出List List list = o.select("$.data.list[?(@.mobile =~ /^187/)]") .toObject((new ArrayList(){}).getClass()); //或 List list = o.select("$.data.list[?(@.mobile =~ /^187/)]") .toObject((new TypeRef>(){}).getClass()); //demo7:遍历 //如果是个Object o.forEach((k,v)->{ //... }); //如果是个Array o.forEach((v)->{ //... }); //demo8:互转 String xml = "...."; XmlFromer xmlFromer = new XmlFromer(); YmalToer ymalToer = new YmalToer(); //加载xml,输出ymal String ymal = ONode.load(xml,Constants.def(),xmlFromer).to(ymalToer); //加载xml,去掉手机号,再转为java object ONode tmp =ONode.load(xml,Constants.def(),xmlFromer); tmp.select("$..[?(@.mobile)]").forEach(n->n.remove("mobile")); XxxModel m =tmp.toObject(XxxModel.class); ``` ## 关于序列化的特点 #### 对象(与fastJson一致) ```json {"@type":"...","a":1,"b":"2"} ``` #### 数组(与fastJson不同,可以精准反序列化类型;需要特性开启) ```json [{"@type":"..."},[1,2,3]] ``` ## 关于Json path的支持 * 字符串使用单引号,例:\['name'] * 过滤操作用空隔号隔开,例:\[?(@.type == 1)] | 支持操作 | 说明 | | --- | --- | | `$` | 表示根元素 | | `@` | 当前节点(做为过滤表达式的谓词使用) | | `*` | 通用配配符,可以表示一个名字或数字。 | | `..` | 深层扫描。 可以理解为递归搜索。 | | `.` | 表示一个子节点 | | `['' (, '')]` | 表示一个或多个子节点 | | `[ (, )]` | 表示一个或多个数组下标(负号为倒数) | | `[start:end]` | 数组片段,区间为\[start,end),不包含end(负号为倒数) | | `[?()]` | 过滤表达式。 表达式结果必须是一个布尔值。 | | 支持过滤操作符 | 说明 | | --- | --- | | `==` | left等于right(注意1不等于'1') | | `!=` | 不等于 | | `<` | 小于 | | `<=` | 小于等于 | | `>` | 大于 | | `>=` | 大于等于 | | `=~` | 匹配正则表达式[?(@.name =~ /foo.*?/i)] | | `in` | 左边存在于右边 [?(@.size in ['S', 'M'])] | | `nin` | 左边不存在于右边 | | 支持尾部函数 | 说明 | | --- | --- | | `min()` | 计算数字数组的最小值 | | `max()` | 计算数字数组的最大值 | | `avg()` | 计算数字数组的平均值 | | `sum()` | 计算数字数组的汇总值(新加的) | 例:`n.select("$.store.book[0].title")` 或 `n.select("$['store']['book'][0]['title']")` 例:`n.select("$..book.price.min()") //找到最低的价格` # Snack3 接口字典 ```swift //初始化操作 // -asObject() -> self:ONode //将当前节点切换为对象 -asArray() -> self:ONode //将当前节点切换为数组 -asValue() -> self:ONode //将当前节点切换为值 -asNull() -> self:ONode //将当前节点切换为null //检测操作 // -isObject() -> bool //检查当前节点是否为对象 -isArray() -> bool //检查当前节点是否为数组 -isValue() -> bool //检查当前节点是否为值 -isNull() -> bool //检查当前节点是否为null //公共 // -nodeData() -> ONodeData //获取当前节点数据 -nodeType() -> ONodeType //获取当前节点类型 -cfg(cfg:Constants) -> self:ONode //切换配置 -cfg() -> Constants //获取配置 -build(n->..) -> self:ONode //节点构建表达式 -select(jpath:String) -> new:ONode //使用JsonPath表达式选择节点(默认缓存路径编译) -select(jpath:String, useStandard:boolean)-> new:ONode //useStandard:使用标准模式,默认非标准 -select(jpath:String, useStandard:boolean, cacheJpath:boolean)-> new:ONode //cacheJpath:是否缓存javaPath编译成果,默认缓存 -clear() //清除子节点,对象或数组有效 -count() -> int //子节点数量,对象或数组有效 //值操作 // -val() -> OValue //获取节点值数据结构体(如果不是值类型,会自动转换) -val(val:Object) -> self:ONode //设置节点值 //val:为常规类型或ONode -getString() //获取值并以string输出 //如果节点为对象或数组,则输出json -getShort() //获取值并以short输出...(以下同...) -getInt() -getBoolean() -getLong() -getDate() -getFloat() -getDouble() -getDouble(scale:int) -getChar() //对象操作 // -obj() -> Map //获取节点对象数据结构体(如果不是对象类型,会自动转换) -readonly() -> self:ONode //只读形态(get时,不添加子节点) -contains(key:String) -> bool //是否存在对象子节点? -rename(key:String,newKey:String) -> self:ONode //重命名子节点并返回自己 -get(key:String) -> child:ONode //获取对象子节点(不存在,生成新的子节点并返回) -getOrNull(key:String) -> child:ONode //获取对象子节点(不存在,返回null) -getNew(key:String) -> child:ONode //生成新的对象子节点,会清除之前的数据 -set(key:String,val:Object) -> self:ONode //设置对象的子节点(会自动处理类型) -setNode(key:String,val:ONode) -> self:ONode //设置对象的子节点,值为ONode类型 -setAll(obj:ONode) -> self:ONode //设置对象的子节点,将obj的子节点搬过来 -setAll(map:Map) ->self:ONode //设置对象的子节点,将map的成员搬过来 -setAll(map:Map, (n,t)->..) ->self:ONode //设置对象的子节点,将map的成员搬过来,并交由代理处置 -remove(key:String) //移除对象的子节点 -forEach((k,v)->..) -> self:ONode //遍历对象的子节点 //数组操作 // -ary() -> List //获取节点数组数据结构体(如果不是数组,会自动转换) -get(index:int) -> child:ONode //获取数组子节点(超界,返回空节点) -getOrNull(index:int) -> child:ONode //获取数组子节点(超界,返回null) -addNew() -> child:ONode //生成新的数组子节点 -add(val) -> self:ONode //添加数组子节点 //val:为常规类型或ONode -addNode(val:ONode) -> self:ONode //添加数组子节点,值为ONode类型 -addAll(ary:ONode) -> self:ONode //添加数组子节点,将ary的子节点搬过来 -addAll(ary:Collection) -> self:ONode //添加数组子节点,将ary的成员点搬过来 -addAll(ary:Collection,(n,t)->..) -> self:ONode //添加数组子节点,将ary的成员点搬过来,并交由代理处置 -removeAt(index:int) //移除数组的子节点 -forEach(v->..) -> self:ONode //遍历数组的子节点 //特性操作(不破坏数据的情况上,添加数据;或用于构建xml dom) // -attrGet(key:String) -> String //获取特性 -attrSet(key:String,val:String) -> self:ONode //设置特性 -attrForeach((k,v)->..) -> self:ONode //遍历特性 //转换操作 // -toString() -> String //转为string (由字符串转换器决定,默认为json) -toJson() -> String //转为json string -toData() -> Object //转为数据结构体(Map,List,Value) -toObject(clz:Class) -> T //转为java object(clz=Object.class:自动输出类型) -to(toer:Toer, clz:Class) -> T //将当前节点通过toer进行转换 -to(toer:Toer) -> T //将当前节点通过toer进行转换 //填充操作(为当前节点填充数据;source 为 String 或 java object) -fill(source:Object) -> self:ONode //填充数据 -fill(source:Object, fromer:Fromer) -> self:ONode //填充数据,由fromer决定处理 /** * 以下为静态操作 **/ //加载操作(source 为 String 或 java object) // +load(source:Object) -> new:ONode //加载数据 +load(source:Object, cfg:Constants) -> new:ONode +load(source:Object, cfg:Constants, fromer:Fromer) -> new:ONode //加载 string +loadStr(source:String) -> new:ONode //仅String //加载 java object +loadObj(source:Object) -> new:ONode //仅java object //字符串化操作 // +stringify(source:Object) -> String //字符串化; //序列化操作 // +serialize(source:Object) -> String //序列化(带@type属性) +deserialize(source:String) -> T //反序列化 +deserialize(source:String, clz:Class) -> T //反序列化 ```