gpt4 book ai didi

c# - Web Api 2 DatetimeOffset XML 序列化问题

转载 作者:数据小太阳 更新时间:2023-10-29 01:57:55 27 4
gpt4 key购买 nike

下面是我模型中的属性:

 public DateTimeOffset AcquireDate { get; set; }

下面是WebApiConfig中的配置:

config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
config.Formatters.Add(new XmlMediaTypeFormatter());

以下是 json 响应(日期为 IS 8601 格式):

enter image description here

下面是 XML 响应:

<AcquireDate xmlns:d3p1="http://schemas.datacontract.org/2004/07/System">
<d3p1:DateTime>2008-01-10T16:40:12.1523923Z</d3p1:DateTime>
<d3p1:OffsetMinutes>330</d3p1:OffsetMinutes>
</AcquireDate>

来自 fiddler :

enter image description here

在Xml 响应中,datetime 和offset 在两个不同的元素中可用。我希望 DateTimeOffset 作为单个值,就像 json 响应(ISO 8601 格式)一样。

我可以再使用一个字符串类型的属性,这样我的问题就可以解决(空 setter 需要序列化该属性)。

[DataMember(Name="AcquireDate")]
public string AcquireDateString
{
get
{
return AcquireDate.ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz");
}
set {
AcquireDate = DateTimeOffset.Parse(value);
}
}

除此之外还有其他解决方案吗?

解决方案不应影响工作正常的现有 Json 序列化。

最佳答案

让我们了解 DateTimeOffset 为您提供 UTC 时间以及该值与 UTC 的差异。因此,该值始终明确标识单个时间点。这是您可能不想泄露的非常有值(value)的信息。但如果由于要求您必须只存储偏移量,请继续阅读下面的解决方案。

既然您可以灵活地将类型从 DateTimeOffset 更改为字符串,那么也许您可以稍微更改类型并仍然使用 DateTimeOffset。

例如,

using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using Newtonsoft.Json;

namespace ConsoleApplication8
{
public struct Iso8601SerializableDateTimeOffset : IXmlSerializable
{
public DateTimeOffset value;

public Iso8601SerializableDateTimeOffset(DateTimeOffset value)
{
this.value = value;
}

public static implicit operator Iso8601SerializableDateTimeOffset(DateTimeOffset value)
{
return new Iso8601SerializableDateTimeOffset(value);
}

public static implicit operator DateTimeOffset(Iso8601SerializableDateTimeOffset instance)
{
return instance.value;
}

public static bool operator ==(Iso8601SerializableDateTimeOffset a, Iso8601SerializableDateTimeOffset b)
{
return a.value == b.value;
}

public static bool operator !=(Iso8601SerializableDateTimeOffset a, Iso8601SerializableDateTimeOffset b)
{
return a.value != b.value;
}

public static bool operator <(Iso8601SerializableDateTimeOffset a, Iso8601SerializableDateTimeOffset b)
{
return a.value < b.value;
}

public static bool operator >(Iso8601SerializableDateTimeOffset a, Iso8601SerializableDateTimeOffset b)
{
return a.value > b.value;
}

public override bool Equals(object o)
{
if (o is Iso8601SerializableDateTimeOffset)
return value.Equals(((Iso8601SerializableDateTimeOffset)o).value);
else if (o is DateTimeOffset)
return value.Equals((DateTimeOffset)o);
else
return false;
}

public override int GetHashCode()
{
return value.GetHashCode();
}

public XmlSchema GetSchema()
{
return null;
}

public void ReadXml(XmlReader reader)
{
var text = reader.ReadElementString();
value = DateTimeOffset.ParseExact(text, format: "o", formatProvider: null);
}

public override string ToString()
{
return value.ToString(format: "o");
}

public string ToString(string format)
{
return value.ToString(format);
}

public void WriteXml(XmlWriter writer)
{
writer.WriteString(value.ToString(format: "o"));
}
}

public class Foo
{
public Guid Id { get; set; }

[JsonConverter(typeof(UtcDateTimeOffsetConverter))]
public Iso8601SerializableDateTimeOffset AcquireDate { get; set; }
}


class Program
{
static void Main(string[] args)
{
var foo = new Foo {
Id = Guid.NewGuid(),
AcquireDate = DateTimeOffset.Now
};

var xmlSerializer = new System.Xml.Serialization.XmlSerializer(foo.GetType());
xmlSerializer.Serialize(Console.Out, foo);
Console.WriteLine();
Console.ReadLine();
}
}
}

输出

<?xml version="1.0" encoding="IBM437"?>
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Id>830cabe2-340b-42c6-bad4-12b5b8b1c43f</Id>
<AcquireDate>2016-03-14T10:47:51.8162249-04:00</AcquireDate>
</Foo>

对于 JSON,我们需要一个转换器,但我们可以重用 Newtonsoft.Json.Converters.IsoDateTimeConverter

  public class UtcDateTimeOffsetConverter : Newtonsoft.Json.Converters.IsoDateTimeConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is Iso8601SerializableDateTimeOffset)
{
var date = (Iso8601SerializableDateTimeOffset)value;
value = date.value;
}
base.WriteJson(writer, value, serializer);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object value = base.ReadJson(reader, objectType, existingValue, serializer);
if (value is Iso8601SerializableDateTimeOffset)
{
var date = (Iso8601SerializableDateTimeOffset)value;
value = date.value;
}
return value;
}
}

Controller

public class ValuesController : ApiController
{
public class Foo
{
public Guid Id { get; set; }

[JsonConverter(typeof(UtcDateTimeOffsetConverter))]
public Iso8601SerializableDateTimeOffset AcquireDate { get; set; }
}

// GET api/values
public IEnumerable<Foo> Get()
{
return new Foo[] {
new Foo() {
Id = Guid.NewGuid(),
AcquireDate = DateTimeOffset.Now
}
};
}
}

输出

<ArrayOfFoo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebApplication1.Models">
<Foo>
<AcquireDate>2016-03-14T12:04:30.2791167-04:00</AcquireDate>
<Id>b3188528-f854-454a-bf9f-9822ff27dc6f</Id>
</Foo>
</ArrayOfFoo>

JSON

[{"Id":"e24bc769-3463-4320-b39a-9ff97e709142","AcquireDate":"2016-03-15T10:47:29.3061449-04:00"}]

完整示例可以在 github 上找到:https://github.com/alexnolasco/DatetimeOffsetXMLSerializationExample

另请参阅:How can I XML Serialize a DateTimeOffset Property?

Choosing Between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo

关于c# - Web Api 2 DatetimeOffset XML 序列化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35866155/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com