我在Java和C#之间交换JSON消息(反之亦然)。
在Java中,我使用java.time.Instant(JSR-310)来表示全局时间轴上的某个时间点。为了在JSON中创建人类可读的日期/时间字符串,我将我的Instant转换如下:
private static final DateTimeFormatter FORMATTER = ofPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZone(ZoneId.systemDefault());
生成以下输出:
2017-04-28T19:54:44-0500
现在,在消息的消费者方面(C#),我编写了一个自定义的Newtonsoft.Json.JsonConverter,它扩展了包含以下重写的ReadJson()方法的抽象JsonCreationConvert类:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
if (reader.TokenType == JsonToken.StartArray)
{
return JToken.Load(reader).ToObject<string[]>();
}
reader.DateParseHandling = DateParseHandling.None; // read NodaTime string Instant as is
serializer.Converters.Add(NodaConverters.InstantConverter);
// Load JObject from stream
var jObject = JObject.Load(reader);
// Create target object based on JObject
T target = Create(objectType, jObject);
// Populate the object properties
var writer = new StringWriter();
serializer.Serialize(writer, jObject);
using (var newReader = new JsonTextReader(new StringReader(writer.ToString())))
{
newReader.Culture = reader.Culture;
newReader.DateParseHandling = reader.DateParseHandling;
newReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
newReader.FloatParseHandling = reader.FloatParseHandling;
serializer.Populate(newReader, target);
}
return target;
}
Create()是一种抽象方法。
当我现在通过调用:
将此JSON字符串转换为NodaTime.Instant(v2.0.0)时InstantPattern.General.Parse(creationTime).Value;
我得到了这个例外:
NodaTime.Text.UnparsableValueException: The value string does not match a quoted string in the pattern. Value being parsed: '2017-04-28T19:54:44^-0500'. (^ indicates error position.)
如果我传递文字文字&#34; Z&#34; (因此没有输出偏移&#34; -0500&#34;并且Z被解释为0偏移)NodaTime.Serialization.JsonNet.NodaConverters.InstantConverter正确读取而不抛出异常。
查看GeneralPatternImpl我看到:
internal static readonly InstantPattern GeneralPatternImpl = InstantPattern.CreateWithInvariantCulture("uuuu-MM-ddTHH:mm:ss'Z'");
为什么InstantConverter要求偏移量是文本字面值?这是否发生是因为Instant与偏移量无关?如果是这种情况,那么为什么InstantConverter不会忽略偏移而不是抛出异常?我是否需要编写自定义转换器来解决此问题?
答案 0 :(得分:1)
这就像要求2017-04-28T19:54:44
被解析为LocalDate
一样 - 我们会默默地删除那些额外的信息。从根本上说,您在Java中从Instant
到String
的转换是&#34;添加&#34;在原始时刻内并不存在的信息。您最终得到的内容实际上是OffsetDateTime
,而不是Instant
- 它提供的信息比Instant
更多。
您应该决定您真正关心的信息。如果您只关心当前的时间,那么将您的Java序列化更改为使用UTC,它应该以序列化形式结束Z
,一切都会好的。这就是我建议你做的事 - 传播无关的信息会产生误导,IMO。
如果您确实关心系统默认时区中的偏移量,而您对.withZone(ZoneId.systemDefault())
的调用暗示,那么您应该将其解析为OffsetDateTime
on事物的.NET方面。如果您愿意,可以将其转换为Instant
(只需致电ToInstant()
)。