Compare commits

...
2 Commits
5 changed files with 56 additions and 2 deletions
+3
View File
@@ -1,2 +1,5 @@
target/ target/
*.cj.macrocall *.cj.macrocall
# 宏编译产物(构建时自动生成,不入库)
src/macros/*.cjo
src/macros/*.dll
+1 -1
View File
@@ -3,7 +3,7 @@
name = "serialization" name = "serialization"
organization = "simcu" organization = "simcu"
description = "SimApi 全反射 JSON 序列化库(对齐 .NET JsonSerializer.Serialize/Deserialize + SerializerPropertyName/SerializerIgnore 特性)" description = "SimApi 全反射 JSON 序列化库(对齐 .NET JsonSerializer.Serialize/Deserialize + SerializerPropertyName/SerializerIgnore 特性)"
version = "1.0.3" version = "1.1.0"
target-dir = "" target-dir = ""
output-type = "static" output-type = "static"
+12
View File
@@ -12,6 +12,7 @@ package simcu::serialization.json
import std.collection.* import std.collection.*
import std.convert.* import std.convert.*
import std.reflect.* import std.reflect.*
import std.time.*
import stdx.encoding.json.* import stdx.encoding.json.*
import simcu::serialization.common.ReflectionCache import simcu::serialization.common.ReflectionCache
import simcu::serialization.common.FieldMetadata import simcu::serialization.common.FieldMetadata
@@ -62,6 +63,7 @@ public class JsonReader {
case "Float64" => return readFloat64(value) case "Float64" => return readFloat64(value)
case "Float32" => return Float32(readFloat64(value)) case "Float32" => return Float32(readFloat64(value))
case "Rune" => return readChar(value) case "Rune" => return readChar(value)
case "DateTime" | "std.time.DateTime" => return readDateTime(value)
case _ => () case _ => ()
} }
@@ -298,6 +300,15 @@ public class JsonReader {
throw Exception("JsonSerializer: 无法转换为 Char") throw Exception("JsonSerializer: 无法转换为 Char")
} }
private static func readDateTime(v: JsonValue): DateTime {
let s = readString(v)
try {
return DateTime.parse(s, "yyyy-MM-dd HH:mm:ss")
} catch (_: Exception) {
throw Exception("JsonSerializer: 无法转换为 DateTime: ${s}")
}
}
/// 生成某类型的占位默认值(用于构造 Option<X> 的 NoneNone 的参数槽类型是 X)。 /// 生成某类型的占位默认值(用于构造 Option<X> 的 NoneNone 的参数槽类型是 X)。
private static func defaultValueFor(typeName: String): Any { private static func defaultValueFor(typeName: String): Any {
match (typeName) { match (typeName) {
@@ -314,6 +325,7 @@ public class JsonReader {
case "Float64" => return Float64(0.0) case "Float64" => return Float64(0.0)
case "Float32" => return Float32(0.0) case "Float32" => return Float32(0.0)
case "Rune" => return Rune(0) case "Rune" => return Rune(0)
case "DateTime" | "std.time.DateTime" => return DateTime.parse("1970-01-01 00:00:00", "yyyy-MM-dd HH:mm:ss")
case _ => () case _ => ()
} }
// 集合/对象/枚举:反射无参构造;失败则抛异常 // 集合/对象/枚举:反射无参构造;失败则抛异常
+2
View File
@@ -10,6 +10,7 @@ package simcu::serialization.json
import std.collection.* import std.collection.*
import std.reflect.* import std.reflect.*
import std.time.*
import stdx.encoding.json.* import stdx.encoding.json.*
import simcu::serialization.common.ReflectionCache import simcu::serialization.common.ReflectionCache
import simcu::serialization.common.FieldMetadata import simcu::serialization.common.FieldMetadata
@@ -42,6 +43,7 @@ public class JsonWriter {
if (let u64: UInt64 <- value) { return JsonInt(Int64(u64)) } if (let u64: UInt64 <- value) { return JsonInt(Int64(u64)) }
if (let f32: Float32 <- value) { return JsonFloat(Float64(f32)) } if (let f32: Float32 <- value) { return JsonFloat(Float64(f32)) }
if (let c: Rune <- value) { return JsonString("${c}") } if (let c: Rune <- value) { return JsonString("${c}") }
if (let dt: DateTime <- value) { return JsonString(dt.format("yyyy-MM-dd HH:mm:ss")) }
let typeName = TypeInfo.of(value).toString() let typeName = TypeInfo.of(value).toString()
+37
View File
@@ -11,6 +11,7 @@
package simcu::serialization.tests package simcu::serialization.tests
import std.collection.* import std.collection.*
import std.time.*
import std.unittest.* import std.unittest.*
import std.unittest.testmacro.* import std.unittest.testmacro.*
import simcu::serialization.* import simcu::serialization.*
@@ -55,6 +56,13 @@ class User <: BaseUser {
public var temp: String = "secret" // 无下划线 + 忽略 public var temp: String = "secret" // 无下划线 + 忽略
} }
// DateTime 字段测试实体
class Event {
public var _name: String = ""
public var _time: DateTime = DateTime.parse("1970-01-01 00:00:00", "yyyy-MM-dd HH:mm:ss")
public var _optTime: ?DateTime = None
}
// 多层继承:爷(标宏)→ 父(不标宏)→ 子 // 多层继承:爷(标宏)→ 父(不标宏)→ 子
@SerializerParent @SerializerParent
open class GrandParent { open class GrandParent {
@@ -304,6 +312,35 @@ public class JsonSerializerTests {
} }
} }
/// DateTime:输出 yyyy-MM-dd HH:mm:ss 字符串并可反序列化回
@TestCase
public func dateTimeRoundTrip(): Unit {
let e = Event()
e._name = "login"
e._time = DateTime.parse("2026-08-21 02:27:48", "yyyy-MM-dd HH:mm:ss")
e._optTime = Some(DateTime.parse("2026-01-02 03:04:05", "yyyy-MM-dd HH:mm:ss"))
let json = JsonSerializer.Serialize(e)
@Expect(json.contains("\"_time\": \"2026-08-21 02:27:48\""), true)
@Expect(json.contains("\"_optTime\": \"2026-01-02 03:04:05\""), true)
let back = JsonSerializer.Deserialize<Event>(json)
@Expect(back._time.format("yyyy-MM-dd HH:mm:ss"), "2026-08-21 02:27:48")
let optVal: ?DateTime = back._optTime
@Expect(optVal.isSome(), true)
if (let Some(dt) <- optVal) {
@Expect(dt.format("yyyy-MM-dd HH:mm:ss"), "2026-01-02 03:04:05")
}
// 顶层 DateTime 直接序列化
@Expect(JsonSerializer.Serialize(back._time), "\"2026-08-21 02:27:48\"")
// Option<DateTime> None → null
let e2 = Event()
e2._name = "n"
e2._time = DateTime.parse("2026-01-01 00:00:00", "yyyy-MM-dd HH:mm:ss")
let json2 = JsonSerializer.Serialize(e2)
@Expect(json2.contains("\"_optTime\": null"), true)
let back2 = JsonSerializer.Deserialize<Event>(json2)
@Expect(back2._optTime.isNone(), true)
}
/// 宽松类型转换:JSON 数字 ↔ 字符串字段互转 /// 宽松类型转换:JSON 数字 ↔ 字符串字段互转
@TestCase @TestCase
public func looseConversion(): Unit { public func looseConversion(): Unit {