Json.Netでシリアル化するときにカスタムのDateTime形式を指定する


137

ASP.NET Web APIを使用して一部のデータを公開するAPIを開発しています。

APIの1つで、クライアントは日付をyyyy-MM-ddフォーマットで公開することを望んでいます。GlobalConfiguration.Configuration.Formatters.JsonFormatterこれはこのクライアントに非常に固有であるため、グローバル設定(など)を変更したくありません。そして、私はそれを複数のクライアントのためのソリューションで開発しています。

私が考えることができる解決策の1つは、カスタムを作成しJsonConverterてから、それをカスタム書式設定を行う必要があるプロパティに置くことです

例えば

class ReturnObjectA 
{
    [JsonConverter(typeof(CustomDateTimeConverter))]
    public DateTime ReturnDate { get;set;}
}

それを行う簡単な方法が他にあるかどうか疑問に思っています。


16
価値があるのは、APIはユーザーの可読性ではなくコンピューターの可読性のためであるため、ISO 8601などの単一の指定された日付形式に固執することをお勧めします。クライアントがAPIの結果をユーザーに直接表示している場合、またはAPIの独自の日付解析コードを記述している場合、それらは間違っています。表示する日付の書式設定は、最上位のUIレイヤーに任せます。
MCattle 2013年

回答:


162

あなたは正しい軌道に乗っています。グローバル設定は変更できないとおっしゃっていたので、次にJsonConverterお勧めするのは、必要に応じて属性を適用することです。Json.NetにはIsoDateTimeConverter、日付形式を指定できるビルトインがすでに組み込まれていることがわかります。残念ながら、JsonConverter属性の唯一の引数は型であるため、属性を介して形式を設定することはできません。ただし、簡単な解決策がありIsoDateTimeConverterます。をサブクラス化し、サブクラスのコンストラクターで日付形式を指定します。JsonConverter必要な場所に属性を適用し、カスタムコンバーターを指定すると、準備が整います。必要なコード全体を次に示します。

class CustomDateTimeConverter : IsoDateTimeConverter
{
    public CustomDateTimeConverter()
    {
        base.DateTimeFormat = "yyyy-MM-dd";
    }
}

そこに時間を置いてもかまわない場合は、IsoDateTimeConverterをサブクラス化する必要すらありません。デフォルトの日付形式はyyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFKソースコードに表示されている)です。


1
@Koen Zomers-私の日付形式から削除した一重引用符は技術的には正しいですが、ここでは厳密には必要ありません。カスタム日付および時刻フォーマット文字ドキュメントのリテラル文字列区切り文字を参照してください。ただし、私がのデフォルト形式として引用した形式はIsonDateTimeConverterJson.Netソースコードから直接取得されたものです。したがって、私はあなたの編集を元に戻します。
ブライアンロジャース

ここでは引用符を付けても機能せず、引用符を付けなくても機能しましたが、もしそうなら、私はおそらく何か間違ったことをしました。編集してごめんなさい。
Koen Zomers 2014年

96

このアプローチを使用できます:

public class DateFormatConverter : IsoDateTimeConverter
{
    public DateFormatConverter(string format)
    {
        DateTimeFormat = format;
    }
}

次のように使用します。

class ReturnObjectA 
{
    [JsonConverter(typeof(DateFormatConverter), "yyyy-MM-dd")]
    public DateTime ReturnDate { get;set;}
}

DateTimeFormat文字列は、ここで説明されている.NET形式の文字列構文を使用します。https//docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings


5
これは私のために動作しません-私が取得'JsonConverterAttribute' does not contain a constructor that takes 2 arguments
タムコトン

1
これは最も柔軟なソリューションです。次のエラーが発生した場合:は'JsonConverterAttribute' does not contain a constructor that takes 2 arguments、json.netのバージョンが古すぎることを意味します。最新のjson.netバージョンに更新する必要があります。
Florian Lavorel

私のために働く。時間を削除する方法はありますか?したがって、2020-02-12のみを返す(例:T00:00:00
Enrico

53

IsoDateTimeConverterグローバル書式設定を変更せずに、インスタンスを使用して行うこともできます。

string json = JsonConvert.SerializeObject(yourObject,
    new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });

これは引数JsonConvert.SerializeObjectを取るオーバーロードを使用しparams JsonConverter[]ます。


5
同じクラスオブジェクトを多くの場所でシリアル化する場合、受け入れられる答えはこれよりも優れています
kgzdev

16

シリアライザ設定オーバーロードの1つを使用して利用することもできます。

var json = JsonConvert.SerializeObject(someObject, new JsonSerializerSettings() { DateFormatString = "yyyy-MM-ddThh:mm:ssZ" });

または

var json = JsonConvert.SerializeObject(someObject, Formatting.Indented, new JsonSerializerSettings() { DateFormatString = "yyyy-MM-ddThh:mm:ssZ" });

Typeを取るオーバーロードも利用できます。


2
FYI私はあなたが意味を考えるyyyy-MM-ddTHH:mm:ssZ時間..に24時間時計を。
Neek '30 / 11/16

9

ヘルパークラスをビルドしてプロパティ属性に適用する

ヘルパークラス:

public class ESDateTimeConverter : IsoDateTimeConverter
{
    public ESDateTimeConverter()
    {
        base.DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fffZ";
    }
}

あなたのコードは次のように使用します:

[JsonConverter(typeof(ESDateTimeConverter))]
public DateTime timestamp { get; set; }

8
なぜ、他の何人かの人々がすでに述べていることを単に繰り返したのですか?
リアム

3

私が使用している別の解決策があります。文字列プロパティを作成してjsonに使用するだけです。このプロパティは、適切にフォーマットされた日付を返します。

class JSonModel {
    ...

    [JsonProperty("date")]
    public string MyDate { get; set; }

    public string CustomDate {
        get { return MyDate.ToString("DDMMYY"); }
        set { MyDate = DateTime.Parse(value); }
    }

    ...
}

これにより、追加のクラスを作成する必要がなくなります。また、さまざまなデータ形式を作成できます。たとえば、同じDateTimeを使用して、時間の別のプロパティを簡単に作成できます。


0

json convert属性の装飾が機能しない場合がありますが、例外的に「2010-10-01」が有効な日付であると表示されます。このタイプを回避するために、プロパティのjson変換属性を削除し、以下のようにdeserilizedObjectメソッドで言及しました。

var addresss = JsonConvert.DeserializeObject<AddressHistory>(address, new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd" });

0

コンバーター付き

public class CustomDateTimeConverter : IsoDateTimeConverter
    {
        public CustomDateTimeConverter()
        {
            DateTimeFormat = "yyyy-MM-dd";
        }

        public CustomDateTimeConverter(string format)
        {
            DateTimeFormat = format;
        }
    }

デフォルトのカスタム形式で使用できます

class ReturnObjectA 
{
    [JsonConverter(typeof(DateFormatConverter))]
    public DateTime ReturnDate { get;set;}
}

または、プロパティに指定された形式

class ReturnObjectB 
{
    [JsonConverter(typeof(DateFormatConverter), "dd MMM yy")]
    public DateTime ReturnDate { get;set;}
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.