如何在C#中用System.Text.Json反序列化Java Duration至NodaTime Duration?
解决方法
要将Java输出的这种多负号格式的Duration字符串反序列化为NodaTime的Duration类型,需要自定义System.Text.Json转换器来适配格式差异,具体步骤如下:
1. 依赖准备
确保项目已安装以下NuGet包:
NodaTimeNodaTime.Serialization.SystemTextJson
2. 自定义Json转换器
创建继承自JsonConverter<Duration>的类,在读取逻辑中处理Java风格的特殊Duration格式:
using System.Text.Json; using System.Text.Json.Serialization; using NodaTime; using NodaTime.Text; public class JavaDurationConverter : JsonConverter<Duration> { public override Duration Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var durationStr = reader.GetString(); if (string.IsNullOrWhiteSpace(durationStr)) return Duration.Zero; // 处理Java风格的多负号格式:将"PT-328H-46M-43.2082074S"转为标准ISO格式"-PT328H46M43.2082074S" bool hasNegativeComponents = durationStr.Contains("-"); if (hasNegativeComponents) { var normalizedStr = "-" + durationStr.Replace("-", ""); var pattern = DurationPattern.CreateWithInvariantCulture("'%'PTHHmmss.FFFFFFF"); var parseResult = pattern.Parse(normalizedStr); if (parseResult.Success) return parseResult.Value; } // 兼容正常ISO格式的解析 var defaultPattern = DurationPattern.Roundtrip; var defaultParseResult = defaultPattern.Parse(durationStr); return defaultParseResult.Success ? defaultParseResult.Value : Duration.Zero; } public override void Write(Utf8JsonWriter writer, Duration value, JsonSerializerOptions options) { // 序列化时输出标准ISO格式,也可根据需求改为Java风格 writer.WriteStringValue(DurationPattern.Roundtrip.Format(value)); } }
3. 应用转换器反序列化
将自定义转换器加入JsonSerializerOptions,即可完成反序列化:
var options = new JsonSerializerOptions(); options.Converters.Add(new JavaDurationConverter()); // 示例反序列化操作 var jsonStr = "\"PT-328H-46M-43.2082074S\""; var nodaDuration = JsonSerializer.Deserialize<Duration>(jsonStr, options); // 验证结果(输出应为 -328:46:43.2082074) Console.WriteLine(nodaDuration);
格式说明
Java的Duration会为每个负分量单独添加负号,而NodaTime默认遵循ISO 8601标准(仅在整个Duration前添加一个负号)。自定义转换器的核心是将Java格式转换为NodaTime可识别的标准格式,再通过DurationPattern完成解析。
内容的提问来源于stack exchange,提问作者NightCity10932
相关产品推荐
相关产品推荐

