更改项目名为NebulaShell
This commit is contained in:
83
store/@{NebulaShell}/json-codec/README.md
Normal file
83
store/@{NebulaShell}/json-codec/README.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# json-codec JSON 编解码器
|
||||
|
||||
提供插件间 JSON 数据的编码、解码和验证功能。
|
||||
|
||||
## 功能
|
||||
|
||||
- **JSON 编码**: Python 对象 → JSON 字符串
|
||||
- **JSON 解码**: JSON 字符串 → Python 对象
|
||||
- **Schema 验证**: 验证 JSON 数据结构
|
||||
- **自定义类型**: 支持注册自定义类型编解码器
|
||||
|
||||
## 基本使用
|
||||
|
||||
```python
|
||||
codec = plugin_mgr.get("json-codec")
|
||||
|
||||
# 编码
|
||||
data = {"name": "test", "count": 42}
|
||||
json_str = codec.encode(data)
|
||||
# '{"name": "test", "count": 42}'
|
||||
|
||||
# 编码(格式化)
|
||||
json_pretty = codec.encode(data, pretty=True)
|
||||
# '{\n "name": "test",\n "count": 42\n}'
|
||||
|
||||
# 解码
|
||||
parsed = codec.decode(json_str)
|
||||
# {"name": "test", "count": 42}
|
||||
```
|
||||
|
||||
## HTTP 响应处理
|
||||
|
||||
```python
|
||||
# 在 http-api 插件中使用
|
||||
router.get("/api/users", lambda req: Response(
|
||||
status=200,
|
||||
headers={"Content-Type": "application/json"},
|
||||
body=codec.encode({"users": [...]})
|
||||
))
|
||||
```
|
||||
|
||||
## Schema 验证
|
||||
|
||||
```python
|
||||
# 注册 schema
|
||||
codec.register_schema("user", {
|
||||
"type": "object",
|
||||
"required": ["name", "email"],
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"email": {"type": "string"},
|
||||
"age": {"type": "number"}
|
||||
}
|
||||
})
|
||||
|
||||
# 验证数据
|
||||
user_data = {"name": "test", "email": "test@example.com"}
|
||||
is_valid = codec.validate(user_data, "user")
|
||||
```
|
||||
|
||||
## 自定义类型
|
||||
|
||||
```python
|
||||
from datetime import datetime
|
||||
|
||||
# 注册自定义编码器
|
||||
codec.serializer.register_encoder(datetime, lambda dt: dt.isoformat())
|
||||
|
||||
# 使用
|
||||
data = {"created_at": datetime.now()}
|
||||
json_str = codec.encode(data)
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
```python
|
||||
from oss.plugin.types import JsonCodecError
|
||||
|
||||
try:
|
||||
result = codec.decode("invalid json")
|
||||
except JsonCodecError as e:
|
||||
print(f"解码失败: {e}")
|
||||
```
|
||||
8
store/@{NebulaShell}/json-codec/SIGNATURE
Normal file
8
store/@{NebulaShell}/json-codec/SIGNATURE
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"signature": "IQ8WAvKno6pRp71kIaxXPb7DzTajPeNOQ0FLZMVovufeyTRMbdSJ8z2zQPBPv9O2a1S9bucyZyhg54fNB2DdLfEnrAbmpepZ3CLrj3cn4KaLNGJjxGHYXWIsFXFvLaYIod/ZuFMYPlzDdwnHJwzHZnkGAmCLrJSR+XvuOqYu/xSZekD/nbMI0fj9VKjaH/S/vopEhq7IFioahVkiSokdYx5qkXYruOVAq3wCnk6O0uCNMfHiIaRhn5pEoQ+VOXcuKX5eOBEph8oXqb+ew1MB917Z1CpaLFuZTyp2Dy8OOmpXjBxfd5VYazH4ZvE9Q7VODHkRDVF2ApkPxTE1k490YvmNOHRamjcf1/mKyu7Myaemtz9oxvZFFiOMOaXBXGfe1wlnsbO832lURTpPu9WXQ6aoDEVp3TNuR/G/xYOXHcWhG1M4tIWW+1ZFcozkVw9cMYvwrVI9JEa89sueXQhJG9foW4nj0DJqmtXaXvcVHnpbFkIxcKFZ0rOMelJ7404XuDb07/sjliJuqCG9Gssmv7/DqNgIrcWUPg24U4UPWW2vWJaJq7HOrGrxFoOxpCT/G4A0WcAWVJrM5NojnfvBNswybSB2IIbspmPRDVtoHQ5a3YJqSLZdgugHh+MbGKlyDvPkQTkPLLE8nrP2F0LwWCq0cYeodE+zU0rZ6CHgAsc=",
|
||||
"signer": "NebulaShell",
|
||||
"algorithm": "RSA-SHA256",
|
||||
"timestamp": 1775964952.836965,
|
||||
"plugin_hash": "a7f7a20614a2e159e393a95c99b15a0a028724694bda3d089787cb41eceba7c4",
|
||||
"author": "NebulaShell"
|
||||
}
|
||||
162
store/@{NebulaShell}/json-codec/main.py
Normal file
162
store/@{NebulaShell}/json-codec/main.py
Normal file
@@ -0,0 +1,162 @@
|
||||
"""JSON 编解码器 - 插件间 JSON 数据处理"""
|
||||
import json
|
||||
from typing import Any, Callable, Optional
|
||||
from datetime import datetime
|
||||
|
||||
from oss.logger.logger import Log
|
||||
from oss.plugin.types import Plugin, register_plugin_type
|
||||
|
||||
|
||||
class JsonCodecError(Exception):
|
||||
"""JSON 编解码错误"""
|
||||
pass
|
||||
|
||||
|
||||
class JsonSerializer:
|
||||
"""JSON 序列化器"""
|
||||
|
||||
def __init__(self):
|
||||
self._custom_encoders: dict[type, Callable] = {}
|
||||
|
||||
def register_encoder(self, type_class: type, encoder: Callable):
|
||||
"""注册自定义类型编码器"""
|
||||
self._custom_encoders[type_class] = encoder
|
||||
|
||||
def encode(self, data: Any, pretty: bool = False) -> str:
|
||||
"""编码为 JSON 字符串"""
|
||||
def default_handler(obj):
|
||||
if isinstance(obj, datetime):
|
||||
return obj.isoformat()
|
||||
for type_class, encoder in self._custom_encoders.items():
|
||||
if isinstance(obj, type_class):
|
||||
return encoder(obj)
|
||||
raise TypeError(f"无法序列化类型: {type(obj).__name__}")
|
||||
|
||||
if pretty:
|
||||
return json.dumps(data, ensure_ascii=False, indent=2, default=default_handler)
|
||||
return json.dumps(data, ensure_ascii=False, default=default_handler)
|
||||
|
||||
def encode_to_bytes(self, data: Any) -> bytes:
|
||||
"""编码为字节"""
|
||||
return self.encode(data).encode("utf-8")
|
||||
|
||||
|
||||
class JsonDeserializer:
|
||||
"""JSON 反序列化器"""
|
||||
|
||||
def __init__(self):
|
||||
self._custom_decoders: dict[str, Callable] = {}
|
||||
|
||||
def register_decoder(self, type_name: str, decoder: Callable):
|
||||
"""注册自定义类型解码器"""
|
||||
self._custom_decoders[type_name] = decoder
|
||||
|
||||
def decode(self, text: str) -> Any:
|
||||
"""解码 JSON 字符串"""
|
||||
try:
|
||||
return json.loads(text)
|
||||
except json.JSONDecodeError as e:
|
||||
raise JsonCodecError(f"JSON 解码失败: {e}")
|
||||
|
||||
def decode_bytes(self, data: bytes) -> Any:
|
||||
"""解码字节"""
|
||||
return self.decode(data.decode("utf-8"))
|
||||
|
||||
def decode_file(self, path: str) -> Any:
|
||||
"""解码 JSON 文件"""
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return self.decode(f.read())
|
||||
|
||||
|
||||
class JsonValidator:
|
||||
"""JSON 验证器"""
|
||||
|
||||
def __init__(self):
|
||||
self._schemas: dict[str, dict] = {}
|
||||
|
||||
def register_schema(self, name: str, schema: dict):
|
||||
"""注册 schema"""
|
||||
self._schemas[name] = schema
|
||||
|
||||
def validate(self, data: Any, schema_name: str) -> bool:
|
||||
"""验证数据是否符合 schema"""
|
||||
if schema_name not in self._schemas:
|
||||
raise JsonCodecError(f"未知的 schema: {schema_name}")
|
||||
return self._check_schema(data, self._schemas[schema_name])
|
||||
|
||||
def _check_schema(self, data: Any, schema: dict) -> bool:
|
||||
"""检查 schema 匹配"""
|
||||
schema_type = schema.get("type")
|
||||
if schema_type == "object":
|
||||
if not isinstance(data, dict):
|
||||
return False
|
||||
required = schema.get("required", [])
|
||||
for field in required:
|
||||
if field not in data:
|
||||
return False
|
||||
properties = schema.get("properties", {})
|
||||
for key, value in data.items():
|
||||
if key in properties:
|
||||
if not self._check_schema(value, properties[key]):
|
||||
return False
|
||||
return True
|
||||
elif schema_type == "array":
|
||||
if not isinstance(data, list):
|
||||
return False
|
||||
items_schema = schema.get("items", {})
|
||||
return all(self._check_schema(item, items_schema) for item in data)
|
||||
elif schema_type == "string":
|
||||
return isinstance(data, str)
|
||||
elif schema_type == "number":
|
||||
return isinstance(data, (int, float))
|
||||
elif schema_type == "boolean":
|
||||
return isinstance(data, bool)
|
||||
return True
|
||||
|
||||
|
||||
class JsonCodecPlugin(Plugin):
|
||||
"""JSON 编解码器插件"""
|
||||
|
||||
def __init__(self):
|
||||
self.serializer = JsonSerializer()
|
||||
self.deserializer = JsonDeserializer()
|
||||
self.validator = JsonValidator()
|
||||
|
||||
def init(self, deps: dict = None):
|
||||
"""初始化"""
|
||||
pass
|
||||
|
||||
def start(self):
|
||||
"""启动"""
|
||||
Log.info("json-codec", "JSON 编解码器已启动")
|
||||
|
||||
def stop(self):
|
||||
"""停止"""
|
||||
pass
|
||||
|
||||
def encode(self, data: Any, pretty: bool = False) -> str:
|
||||
"""编码 JSON"""
|
||||
return self.serializer.encode(data, pretty)
|
||||
|
||||
def decode(self, text: str) -> Any:
|
||||
"""解码 JSON"""
|
||||
return self.deserializer.decode(text)
|
||||
|
||||
def validate(self, data: Any, schema_name: str) -> bool:
|
||||
"""验证 JSON schema"""
|
||||
return self.validator.validate(data, schema_name)
|
||||
|
||||
def register_schema(self, name: str, schema: dict):
|
||||
"""注册 schema"""
|
||||
self.validator.register_schema(name, schema)
|
||||
|
||||
|
||||
# 注册类型
|
||||
register_plugin_type("JsonSerializer", JsonSerializer)
|
||||
register_plugin_type("JsonDeserializer", JsonDeserializer)
|
||||
register_plugin_type("JsonValidator", JsonValidator)
|
||||
register_plugin_type("JsonCodecError", JsonCodecError)
|
||||
|
||||
|
||||
def New():
|
||||
return JsonCodecPlugin()
|
||||
15
store/@{NebulaShell}/json-codec/manifest.json
Normal file
15
store/@{NebulaShell}/json-codec/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"metadata": {
|
||||
"name": "json-codec",
|
||||
"version": "1.0.0",
|
||||
"author": "NebulaShell",
|
||||
"description": "JSON 编解码器 - 插件间 JSON 数据处理和验证",
|
||||
"type": "utility"
|
||||
},
|
||||
"config": {
|
||||
"enabled": true,
|
||||
"args": {}
|
||||
},
|
||||
"dependencies": [],
|
||||
"permissions": []
|
||||
}
|
||||
Reference in New Issue
Block a user