web-dev-qa-db-ja.com

XmlSerializerがDateTimeを 'YYYY-MM-DD hh:mm:ss'としてシリアル化するように強制します

RESTfulサービスのXSDスキーマがあります。 xsd.exeツールと組み合わせて使用​​してC#コードを生成すると、XSDのxs:dateは次のコードを生成します。

[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="date")]
public System.DateTime time {
    get {
        return this.timeField;
    }
    set {
        this.timeField = value;
    }
}

XmlSerializerを使用してXMLをオブジェクトにデシリアライズするとき、すべてがうまくいくようです。私が直面している問題は、サービスが日付がYYYY-MM-DD hh:mm:ssとしてフォーマットされることを期待し、XSD生成コードがYYYY-MM-DDのみを生成するように見えることです。

XSDを手動でxs:dateTimeタイプに変更すると、生成されたC#コードは2010-08-20T20:07:03.915039Zを生成します。

基本的に、シリアル化でYYYY-MM-DD hh:mm:ssを生成するにはどうすればよいですか? XSDに何かすることはありますか、または生成されたC#コードを変更するためにできることはありますか?

63
wpfwannabe

過去に、日時のシリアル化を制御するために次のことを行いました。

  • DateTimeプロパティを無視します。
  • 私が望む方法をシリアライズ/デシリアライズするダミー文字列プロパティを作成します

以下に例を示します。

public class SomeClass
{
    [XmlIgnore]
    public DateTime SomeDate { get; set; }

    [XmlElement("SomeDate")]
    public string SomeDateString
    {
        get { return this.SomeDate.ToString("yyyy-MM-dd HH:mm:ss"); }
        set { this.SomeDate = DateTime.Parse(value); }
    }
}
125
kbrimington

[XmlElement(DataType = "date")]属性を使用して、必要に応じてDateTimeプロパティ値をフォーマットします。

MSDNから

注意:
publicationdateフィールドに注釈を付ける属性には、DataTypeプロパティがあります。 .NET Frameworkには、xs:date型に完全に一致する型はありません。最も近いものはSystem.DateTimeで、日付と時刻のデータが保存されます。 DataTypeプロパティを「日付」として指定すると、XmlSerializerはDateTimeオブジェクトの日付部分のみをシリアル化します。

52
Bill Gates

IXmlSerializableインターフェースを実装するとうまくいくと思います。その後、オブジェクトのシリアル化と逆シリアル化の方法を制御できます。

3
Eric

ミリ秒部分のみをクリアする必要がある場合。参照する:

。NET DateTimeからミリ秒を切り捨てる方法

そして基本的に次のようなことをします:

  startDateTimeToUse = startDateTimeToUse.AddTicks(-(startDateTimeToUse.Ticks % TimeSpan.TicksPerSecond));
  endDate = endDate.AddTicks(-(endDate.Ticks % TimeSpan.TicksPerSecond));

これが次のようにシリアライズされることを確認できます。

            <startDate>2015-10-31T12:13:04</startDate>
            <endDate>2016-11-10T12:13:06</endDate>

私はまた、Beforeミリ秒をクリアすることを述べなければなりません:

            var startDateTimeToUse = ssStartDateTime.ToUniversalTime();
            var endDate = DateTime.Now.ToUniversalTime();
            startDateTimeToUse = DateTime.SpecifyKind(startDateTimeToUse, DateTimeKind.Unspecified);
            endDate = DateTime.SpecifyKind(endDate, DateTimeKind.Unspecified);

この時点でシリアル化に影響があるかどうかはわかりません

1
João Antunes

上記の回答をご覧ください。ただし、値がnullでない場合(XML maxOccurs = 0など)にのみ出力が必要な場合は、次のようなものを利用できます。

private System.DateTime? someDateField;

public string someDate
{
    get
    {
        return someDateField?.ToString("MM-dd-yyyy");
    }
    set
    {
        dobField = System.DateTime.Parse(value);
    }
}
1
Brian