chore: 发布准备——修复 cjlint MANDATORY 错误 + 补 org 配置
publish 流程会执行 cjlint(error 即阻塞),修复: - 测试枚举 Role.User 与类型名 User 冲突 → 改名 Role.Member(G.ENU.01) - 测试用例函数补 : Unit 返回类型(G.DCL.02) - JsonOption.instance 补显式类型(G.DCL.02) - JsonReader.readParentFields 移除未使用 options 参数(G.FUN.02) - Annotations.cj 移除硬编码 URL(G.OTH.03) - 宏 FieldVisitor.visit 补 : Unit(G.DCL.02) - cjpm.toml 增加 org = "simcu"(publish 自动写入) cjpm bundle 已可成功生成 simapi_serialization-1.0.0.cjp, 剩余阻塞:中心仓认证(pkg.cangjie-lang.cn 需用户 token)
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
name = "simapi_serialization"
|
name = "simapi_serialization"
|
||||||
description = "SimApi 全反射 JSON 序列化库(对齐 .NET JsonSerializer.Serialize/Deserialize + SerializerPropertyName/SerializerIgnore 特性)"
|
description = "SimApi 全反射 JSON 序列化库(对齐 .NET JsonSerializer.Serialize/Deserialize + SerializerPropertyName/SerializerIgnore 特性)"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
org = "simcu"
|
||||||
target-dir = ""
|
target-dir = ""
|
||||||
output-type = "static"
|
output-type = "static"
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,6 @@
|
|||||||
* 设计决策:本库序列化/反序列化只处理「var 成员变量」(std.reflect 的 instanceVariables),
|
* 设计决策:本库序列化/反序列化只处理「var 成员变量」(std.reflect 的 instanceVariables),
|
||||||
* 不处理 prop 属性(instanceProperties)。因此注解 target 仅限 MemberVariable:
|
* 不处理 prop 属性(instanceProperties)。因此注解 target 仅限 MemberVariable:
|
||||||
* 标到 prop 上会直接编译报错,避免「标了但不生效」的静默陷阱。
|
* 标到 prop 上会直接编译报错,避免「标了但不生效」的静默陷阱。
|
||||||
*
|
|
||||||
* 参考仓颉官方注解用法(std.reflect 运行时读取):
|
|
||||||
* https://docs.cangjie-lang.cn/en/docs/1.0.0/libs/std/reflect/reflect_samples/annotation.html
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package simapi_serialization.common
|
package simapi_serialization.common
|
||||||
|
|||||||
@@ -23,5 +23,5 @@ public class JsonOption {
|
|||||||
public init() {}
|
public init() {}
|
||||||
|
|
||||||
/// 默认选项实例
|
/// 默认选项实例
|
||||||
public static let instance = JsonOption()
|
public static let instance: JsonOption = JsonOption()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,14 +137,14 @@ public class JsonReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 父类字段(@SerializerParent 宏生成的静态导入方法,沿继承链逐层回填)
|
// 父类字段(@SerializerParent 宏生成的静态导入方法,沿继承链逐层回填)
|
||||||
readParentFields(value, ct, instance, options)
|
readParentFields(value, ct, instance)
|
||||||
instance
|
instance
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 沿 superClass 链调用每层的 importJsonFields 静态方法回填父类字段。
|
/// 沿 superClass 链调用每层的 importJsonFields 静态方法回填父类字段。
|
||||||
/// 无宏的父类(hasImportFields 缓存判断)静默跳过;宏生成的方法内部按
|
/// 无宏的父类(hasImportFields 缓存判断)静默跳过;宏生成的方法内部按
|
||||||
/// if (k == "字段名") 忽略未知键,因此直接把全部 JSON 键传入即可。
|
/// if (k == "字段名") 忽略未知键,因此直接把全部 JSON 键传入即可。
|
||||||
private static func readParentFields(value: JsonValue, ct: ClassTypeInfo, instance: Any, options: JsonOption): Unit {
|
private static func readParentFields(value: JsonValue, ct: ClassTypeInfo, instance: Any): Unit {
|
||||||
let jobj = value.asObject()
|
let jobj = value.asObject()
|
||||||
var parent = ct.superClass
|
var parent = ct.superClass
|
||||||
while (let Some(p) <- parent) {
|
while (let Some(p) <- parent) {
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ private func unwrapMacroField(md: MacroExpandDecl): ?VarDecl {
|
|||||||
private class FieldVisitor <: Visitor {
|
private class FieldVisitor <: Visitor {
|
||||||
private var _decl: ?VarDecl = None
|
private var _decl: ?VarDecl = None
|
||||||
|
|
||||||
public override func visit(decl: VarDecl) {
|
public override func visit(decl: VarDecl): Unit {
|
||||||
_decl = Some(decl)
|
_decl = Some(decl)
|
||||||
this.breakTraverse()
|
this.breakTraverse()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import simapi_serialization.*
|
|||||||
import simapi_serialization.macros.*
|
import simapi_serialization.macros.*
|
||||||
enum Role {
|
enum Role {
|
||||||
| Admin
|
| Admin
|
||||||
| User
|
| Member
|
||||||
| Guest
|
| Guest
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ class User <: BaseUser {
|
|||||||
public var _age: Int64 = 0 // 下划线字段
|
public var _age: Int64 = 0 // 下划线字段
|
||||||
public var score: Float64 = 0.0 // 无下划线
|
public var score: Float64 = 0.0 // 无下划线
|
||||||
public var active: Bool = true // 无下划线
|
public var active: Bool = true // 无下划线
|
||||||
public var _role: Role = Role.User // 下划线字段(枚举)
|
public var _role: Role = Role.Member // 下划线字段(枚举)
|
||||||
public var opt: ?String = None // 无下划线(Option=Some)
|
public var opt: ?String = None // 无下划线(Option=Some)
|
||||||
public var remark: ?String = None // 无下划线(Option=None → null)
|
public var remark: ?String = None // 无下划线(Option=None → null)
|
||||||
public var _tags: Array<String> = [] // 下划线字段(集合)
|
public var _tags: Array<String> = [] // 下划线字段(集合)
|
||||||
@@ -109,7 +109,7 @@ func makeUser(): User {
|
|||||||
func roleStr(r: Role): String {
|
func roleStr(r: Role): String {
|
||||||
match (r) {
|
match (r) {
|
||||||
case Role.Admin => "Admin"
|
case Role.Admin => "Admin"
|
||||||
case Role.User => "User"
|
case Role.Member => "User"
|
||||||
case Role.Guest => "Guest"
|
case Role.Guest => "Guest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ func toStr(x: Any): String {
|
|||||||
public class JsonSerializerTests {
|
public class JsonSerializerTests {
|
||||||
/// 基础类型序列化
|
/// 基础类型序列化
|
||||||
@TestCase
|
@TestCase
|
||||||
public func basicTypes() {
|
public func basicTypes(): Unit {
|
||||||
@Expect(JsonSerializer.Serialize(Int64(42)), "42")
|
@Expect(JsonSerializer.Serialize(Int64(42)), "42")
|
||||||
@Expect(JsonSerializer.Serialize(Int32(7)), "7")
|
@Expect(JsonSerializer.Serialize(Int32(7)), "7")
|
||||||
@Expect(JsonSerializer.Serialize(Int16(3)), "3")
|
@Expect(JsonSerializer.Serialize(Int16(3)), "3")
|
||||||
@@ -137,7 +137,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 对象序列化:下划线保留、注解生效、忽略生效、None→null、父类字段不输出
|
/// 对象序列化:下划线保留、注解生效、忽略生效、None→null、父类字段不输出
|
||||||
@TestCase
|
@TestCase
|
||||||
public func objectSerialize() {
|
public func objectSerialize(): Unit {
|
||||||
let json = JsonSerializer.Serialize(makeUser())
|
let json = JsonSerializer.Serialize(makeUser())
|
||||||
// 下划线字段原样输出
|
// 下划线字段原样输出
|
||||||
@Expect(json.contains("\"_name\": \"alice\""), true)
|
@Expect(json.contains("\"_name\": \"alice\""), true)
|
||||||
@@ -171,7 +171,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 对象反序列化往返
|
/// 对象反序列化往返
|
||||||
@TestCase
|
@TestCase
|
||||||
public func objectRoundTrip() {
|
public func objectRoundTrip(): Unit {
|
||||||
let json = JsonSerializer.Serialize(makeUser())
|
let json = JsonSerializer.Serialize(makeUser())
|
||||||
let u2 = JsonSerializer.Deserialize<User>(json)
|
let u2 = JsonSerializer.Deserialize<User>(json)
|
||||||
@Expect(u2._name, "alice")
|
@Expect(u2._name, "alice")
|
||||||
@@ -203,7 +203,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// Array 往返
|
/// Array 往返
|
||||||
@TestCase
|
@TestCase
|
||||||
public func arrayRoundTrip() {
|
public func arrayRoundTrip(): Unit {
|
||||||
let json = JsonSerializer.Serialize(["x", "y", "z"])
|
let json = JsonSerializer.Serialize(["x", "y", "z"])
|
||||||
let arrBack = JsonSerializer.Deserialize<Array<String>>(json)
|
let arrBack = JsonSerializer.Deserialize<Array<String>>(json)
|
||||||
@Expect(arrBack.size, Int64(3))
|
@Expect(arrBack.size, Int64(3))
|
||||||
@@ -213,7 +213,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// ArrayList 往返
|
/// ArrayList 往返
|
||||||
@TestCase
|
@TestCase
|
||||||
public func arrayListRoundTrip() {
|
public func arrayListRoundTrip(): Unit {
|
||||||
var list = ArrayList<String>()
|
var list = ArrayList<String>()
|
||||||
list.add("a")
|
list.add("a")
|
||||||
list.add("b")
|
list.add("b")
|
||||||
@@ -226,7 +226,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// HashSet 往返
|
/// HashSet 往返
|
||||||
@TestCase
|
@TestCase
|
||||||
public func hashSetRoundTrip() {
|
public func hashSetRoundTrip(): Unit {
|
||||||
var set = HashSet<String>()
|
var set = HashSet<String>()
|
||||||
set.add("x")
|
set.add("x")
|
||||||
set.add("y")
|
set.add("y")
|
||||||
@@ -238,7 +238,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// HashMap<String, V> 往返
|
/// HashMap<String, V> 往返
|
||||||
@TestCase
|
@TestCase
|
||||||
public func hashMapRoundTrip() {
|
public func hashMapRoundTrip(): Unit {
|
||||||
let m = HashMap<String, Any>()
|
let m = HashMap<String, Any>()
|
||||||
m["k1"] = "v1"
|
m["k1"] = "v1"
|
||||||
m["k2"] = Int64(42)
|
m["k2"] = Int64(42)
|
||||||
@@ -250,7 +250,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 命名策略:NONE / CAMEL / SNAKE 对当前模型(全小写+下划线)输出一致
|
/// 命名策略:NONE / CAMEL / SNAKE 对当前模型(全小写+下划线)输出一致
|
||||||
@TestCase
|
@TestCase
|
||||||
public func namingPolicies() {
|
public func namingPolicies(): Unit {
|
||||||
let optNone = JsonOption()
|
let optNone = JsonOption()
|
||||||
optNone.propertyNamingPolicy = PropertyNamingPolicy.Keep
|
optNone.propertyNamingPolicy = PropertyNamingPolicy.Keep
|
||||||
let jsonNone = JsonSerializer.Serialize(makeUser(), optNone)
|
let jsonNone = JsonSerializer.Serialize(makeUser(), optNone)
|
||||||
@@ -270,7 +270,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 命名策略转换规则(直接单测)
|
/// 命名策略转换规则(直接单测)
|
||||||
@TestCase
|
@TestCase
|
||||||
public func applyNamingPolicy() {
|
public func applyNamingPolicy(): Unit {
|
||||||
// SnakeCase:大写转 _小写
|
// SnakeCase:大写转 _小写
|
||||||
@Expect(ReflectionCache.applyNamingPolicy("userName", PropertyNamingPolicy.SnakeCase), "user_name")
|
@Expect(ReflectionCache.applyNamingPolicy("userName", PropertyNamingPolicy.SnakeCase), "user_name")
|
||||||
@Expect(ReflectionCache.applyNamingPolicy("userNameAge", PropertyNamingPolicy.SnakeCase), "user_name_age")
|
@Expect(ReflectionCache.applyNamingPolicy("userNameAge", PropertyNamingPolicy.SnakeCase), "user_name_age")
|
||||||
@@ -285,7 +285,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 枚举序列化/反序列化
|
/// 枚举序列化/反序列化
|
||||||
@TestCase
|
@TestCase
|
||||||
public func enumSerialize() {
|
public func enumSerialize(): Unit {
|
||||||
@Expect(JsonSerializer.Serialize(Role.Admin), "\"Admin\"")
|
@Expect(JsonSerializer.Serialize(Role.Admin), "\"Admin\"")
|
||||||
@Expect(JsonSerializer.Serialize(Role.Guest), "\"Guest\"")
|
@Expect(JsonSerializer.Serialize(Role.Guest), "\"Guest\"")
|
||||||
let u = User()
|
let u = User()
|
||||||
@@ -296,7 +296,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// Option 字段:null → None,值 → Some
|
/// Option 字段:null → None,值 → Some
|
||||||
@TestCase
|
@TestCase
|
||||||
public func optionField() {
|
public func optionField(): Unit {
|
||||||
let none: ?String = JsonSerializer.Deserialize<?String>("null")
|
let none: ?String = JsonSerializer.Deserialize<?String>("null")
|
||||||
@Expect(none.isNone(), true)
|
@Expect(none.isNone(), true)
|
||||||
let some: ?String = JsonSerializer.Deserialize<?String>("\"hi\"")
|
let some: ?String = JsonSerializer.Deserialize<?String>("\"hi\"")
|
||||||
@@ -308,7 +308,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 宽松类型转换:JSON 数字 ↔ 字符串字段互转
|
/// 宽松类型转换:JSON 数字 ↔ 字符串字段互转
|
||||||
@TestCase
|
@TestCase
|
||||||
public func looseConversion() {
|
public func looseConversion(): Unit {
|
||||||
// 数字 → String 字段
|
// 数字 → String 字段
|
||||||
let s: String = JsonSerializer.Deserialize<String>("42")
|
let s: String = JsonSerializer.Deserialize<String>("42")
|
||||||
@Expect(s, "42")
|
@Expect(s, "42")
|
||||||
@@ -325,7 +325,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 深度限制:超过 maxDepth 抛异常
|
/// 深度限制:超过 maxDepth 抛异常
|
||||||
@TestCase
|
@TestCase
|
||||||
public func maxDepth() {
|
public func maxDepth(): Unit {
|
||||||
let opt = JsonOption()
|
let opt = JsonOption()
|
||||||
opt.maxDepth = 0
|
opt.maxDepth = 0
|
||||||
let u = User()
|
let u = User()
|
||||||
@@ -341,7 +341,7 @@ public class JsonSerializerTests {
|
|||||||
/// 父类字段序列化/反序列化(@SerializerParent 宏):已并入 objectSerialize/objectRoundTrip,
|
/// 父类字段序列化/反序列化(@SerializerParent 宏):已并入 objectSerialize/objectRoundTrip,
|
||||||
/// 此处验证宏生成的静态方法可直接调用
|
/// 此处验证宏生成的静态方法可直接调用
|
||||||
@TestCase
|
@TestCase
|
||||||
public func parentMacroMethods() {
|
public func parentMacroMethods(): Unit {
|
||||||
let u = User()
|
let u = User()
|
||||||
u._id = "m-1"
|
u._id = "m-1"
|
||||||
u._createdAt = "2025-02-02"
|
u._createdAt = "2025-02-02"
|
||||||
@@ -365,7 +365,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 多层继承:爷标宏、中间层不标宏 → 爷字段导出,中间层字段不导出
|
/// 多层继承:爷标宏、中间层不标宏 → 爷字段导出,中间层字段不导出
|
||||||
@TestCase
|
@TestCase
|
||||||
public func multiLevelInheritance() {
|
public func multiLevelInheritance(): Unit {
|
||||||
let leaf = LeafChild()
|
let leaf = LeafChild()
|
||||||
leaf._gp = "gp-v"
|
leaf._gp = "gp-v"
|
||||||
leaf._mp = "mp-v"
|
leaf._mp = "mp-v"
|
||||||
@@ -384,7 +384,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 宏自动补 open:GrandParent 未显式写 open(@SerializerParent 自动补),继承链可正常编译
|
/// 宏自动补 open:GrandParent 未显式写 open(@SerializerParent 自动补),继承链可正常编译
|
||||||
@TestCase
|
@TestCase
|
||||||
public func parentAutoOpen() {
|
public func parentAutoOpen(): Unit {
|
||||||
let leaf = LeafChild()
|
let leaf = LeafChild()
|
||||||
leaf._gp = "auto"
|
leaf._gp = "auto"
|
||||||
let json = JsonSerializer.Serialize(leaf)
|
let json = JsonSerializer.Serialize(leaf)
|
||||||
@@ -393,7 +393,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 三级继承(全标宏):爷/父/子 每层字段都导出、反序列化全部回填
|
/// 三级继承(全标宏):爷/父/子 每层字段都导出、反序列化全部回填
|
||||||
@TestCase
|
@TestCase
|
||||||
public func threeLevelAllMacro() {
|
public func threeLevelAllMacro(): Unit {
|
||||||
let leaf = LeafAll()
|
let leaf = LeafAll()
|
||||||
leaf._ga = "ga-v"
|
leaf._ga = "ga-v"
|
||||||
leaf._ma = "ma-v"
|
leaf._ma = "ma-v"
|
||||||
@@ -412,7 +412,7 @@ public class JsonSerializerTests {
|
|||||||
|
|
||||||
/// 三级继承:每层字段互不遮蔽(字段名不同),导出顺序无关,值各自正确
|
/// 三级继承:每层字段互不遮蔽(字段名不同),导出顺序无关,值各自正确
|
||||||
@TestCase
|
@TestCase
|
||||||
public func threeLevelFieldSeparation() {
|
public func threeLevelFieldSeparation(): Unit {
|
||||||
let leaf = LeafAll()
|
let leaf = LeafAll()
|
||||||
leaf._ga = "G"
|
leaf._ga = "G"
|
||||||
leaf._ma = "M"
|
leaf._ma = "M"
|
||||||
|
|||||||
Reference in New Issue
Block a user