通用数据引用表示法:基于协议-URI-JSONPath的简洁数据定位规范
1. 概述
基于协议-URI-JSONPath的模式,隐藏JSONPath的根节点$前缀,提供简洁的数据引用表示法。
2. 语法规范
2.1 完整格式
<protocol>://<uri>#<jsonpath>
其中:
protocol:资源访问协议uri:资源标识符(根据协议而变化)jsonpath:JSONPath表达式,省略根节点$
2.2 协议支持
| 协议 | 描述 | 示例 |
|---|---|---|
file |
本地文件系统 | file:///data/config.json#settings.db |
http/https |
HTTP资源 | https://api.example.com/data.json#items[0] |
data |
内联数据(RFC2397) | data:application/json,...#key |
redis |
Redis存储 | redis://localhost:6379/0#config.app |
env |
环境变量 | env://DATABASE_URL#host |
2.3 JSONPath简化规则
- 隐藏根节点 :所有表达式省略开头的
$ - 自动补全 :解析时自动添加
$前缀 - 特殊字符 :
- 保持
.,[],*,?()等标准语法 - 支持点表示法和括号表示法混合使用
- 保持
3. EBNF 语法定义
(* 完整UDRS语法 *)
udrs-reference = protocol "://" uri [ "#" jsonpath ] ;
(* 协议部分 *)
protocol = scheme ;
scheme = letter, { letter | digit | "+" | "-" | "." } ;
(* URI部分 - 简化定义 *)
uri = uri-scheme-data | uri-path-data ;
uri-scheme-data = scheme-data ; (* 如data:协议 *)
uri-path-data = [ authority ] path ;
authority = "//" [ userinfo "@" ] host [ ":" port ] ;
userinfo = { unreserved | sub-delims | ":" } ;
host = hostname | ipv4address | ipv6address ;
port = digit, { digit } ;
path = { segment } ;
(* JSONPath部分 *)
jsonpath = [ root ] path-expr ;
root = "$" | "@" ; (* 可选,通常省略 *)
path-expr = segment-expr, { ( "." segment-expr ) | bracket-expr } ;
segment-expr = identifier | wildcard ;
bracket-expr = "[", subscript, "]" ;
subscript = numeric-subscript | string-subscript | wildcard | slice | filter-expr ;
numeric-subscript = integer | negative-integer ;
string-subscript = single-quoted-string | double-quoted-string ;
slice = [ integer ], ":", [ integer ], [ ":", [ integer ] ] ;
filter-expr = "?(", boolean-expr, ")" ;
(* 基本元素 *)
identifier = ( letter | "_" ), { letter | digit | "_" } ;
wildcard = "*" ;
integer = [ "-" ], digit, { digit } ;
negative-integer = "-", digit, { digit } ;
(* 字符串 *)
single-quoted-string = "'", { char - "'" }, "'" ;
double-quoted-string = '"', { char - '"' }, '"' ;
(* 布尔表达式 - 简化 *)
boolean-expr = simple-expr, { ( "&&" | "||" ), simple-expr } ;
simple-expr = "@", path-expr, comparison-op, ( literal | "@", path-expr ) ;
comparison-op = "==" | "!=" | "<" | "<=" | ">" | ">=" ;
(* 字面量 *)
literal = string-literal | number-literal | boolean-literal | null-literal ;
string-literal = '"', { char - '"' }, '"' ;
number-literal = integer, [ ".", digit, { digit } ], [ exponent ] ;
exponent = ( "e" | "E" ), [ "+" | "-" ], digit, { digit } ;
boolean-literal = "true" | "false" ;
null-literal = "null" ;
(* 字符类 *)
letter = "a".."z" | "A".."Z" ;
digit = "0".."9" ;
char = ? any Unicode character ? ;
(* URI保留字符 *)
unreserved = letter | digit | "-" | "." | "_" | "~" ;
sub-delims = "!" | "$" | "&" | "'" | "(" | ")" | "*" | "+" | "," | ";" | "=" ;
4. 解析规则
4.1 解析流程
- 协议解析 :提取
://前的部分 - URI解析 :提取
#前的部分(使用标准URI解析) - JSONPath解析 :
- 如果
#后为空:默认为$(根节点) - 如果以
$或@开头:按标准JSONPath处理 - 否则:自动添加
$前缀
- 如果
4.2 示例解析
| UDRS表示法 | 解析后JSONPath | 描述 |
|---|---|---|
file:///data.json#store.book[0] |
$.store.book[0] |
自动添加$ |
file:///data.json#$.store.book[0] |
$.store.book[0] |
已包含$,保持不变 |
file:///data.json#@.name |
@.name |
当前节点,不变 |
file:///data.json# |
$ |
空路径 → 根节点 |
file:///data.json |
$ |
无路径 → 根节点 |
https://example.com/a.json#items[*].id |
$.items[*].id |
通配符数组 |
5. 特殊语法支持
5.1 转义规则
# 点号转义
users."john.doe".email → users['john.doe'].email
# 引号转义
users.'O\'Brien'.name → users["O'Brien"].name
5.2 内联数据
data:application/json,{"items":[{"id":1}]}#items[0]
5.3 查询表达式
# 过滤器表达式
file://data.json#users[?(@.age >= 18)].name
# 切片操作
file://data.json#items[0:5:2]
# 组合使用
file://data.json#users[?(@.active)].emails[*]
6. 错误处理
6.1 语法错误
- 无效协议 :
unknown://... - URI格式错误 :
file://invalid[path].json#... - JSONPath语法错误 :
file://data.json#invalid..path
6.2 语义错误
- 资源不存在 :
file:///nonexistent.json#... - 路径不存在 :
file://data.json#nonexistent.key - 类型不匹配 :
file://data.json#items.name(items为数组)
7. 扩展建议
7.1 可选的类型提示
file://config.yaml#settings.database<uri>
7.2 默认值语法
file://config.json#timeout|30
7.3 函数应用
file://data.json#items|length()
7.4 相对引用
# 当前文件相对路径
./config.json#key
../parent.json#key
# 使用base URI解析
<base>file:///base/path/</base>
sub/config.json#key → file:///base/path/sub/config.json#key
8. 实现建议
8.1 解析库功能
- 分离解析:可单独获取协议、URI、JSONPath
- 规范化:统一处理相对路径、编码
- 验证:语法验证和资源验证分离
- 缓存:资源获取缓存机制
8.2 安全性
- 沙箱:限制文件系统访问
- 递归限制:防止循环引用
- 资源限制:限制远程资源大小
- 白名单:协议和域名白名单
9. 与现有标准的关系
9.1 兼容性
- URI标准:完全兼容RFC 3986
- JSONPath:兼容RFC 9535(JSONPath草案)
- URI片段 :遵循
#作为片段标识符
9.2 优势
- 简洁性 :隐藏了冗余的
$前缀 - 统一性:统一了本地和远程资源引用
- 可扩展:支持多种协议和数据格式
- 可读性:更接近自然语言表达
这个规范平衡了简洁性和表达能力,同时保持了与现有标准的兼容性。