2013-09-05 6 views
58

ASP.NET Web APIを使用して一部のデータを公開するAPIを開発しています。Json.Netでシリアル化するときにカスタムDateTime形式を指定する

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

私は考えることができソリューションの一つは、カスタムJSONコンバーターを作成してから、私は

例えばをカスタム書式を行うために必要なプロパティにそれを置くことです

これを実行する他の簡単な方法があるかどうかは疑問です。

+8

をAPIはコンピュータの可読性を考慮したものであり、ユーザーが読みやすいものではありませんので、[ISO 8601](http://xkcd.com/1179/)などの指定された日付形式を使用することをお勧めします。クライアントが直接API結果をユーザーに表示している場合や、APIの独自の日付解析コードを記述している場合は、間違っています。表示する日付の書式設定は、一番上のUIレイヤーのままにする必要があります。 – MCattle

答えて

91

あなたは正しい方向にあります。グローバル設定を変更することはできないと言ったので、次のベストは、あなたが提案したように、必要に応じて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.FFFFFFFKsource codeのように)です。

+0

@Koen Zomers - 厳密にここでは必要ではありませんが、技術的に私の日付形式から削除した一重引用符は正しいものです。 [Custom Date and Time Format Stringsのドキュメント](http://msdn.microsoft.com/en-us/library/8kb3ddd4(v = vs.110).aspx)の_Literal String Delimiters_を参照してください。しかし、私が 'IsonDateTimeConverter'のデフォルトフォーマットとして引用したフォーマットは、[Json.Netソースコード](http://json.codeplex.com/SourceControl/latest#trunk/Src/Newtonsoft.Json/コンバーター/ IsoDateTimeConverter.cs);私はあなたの編集を元に戻しています。 –

+0

ここでは引用符では機能しませんでしたが、それがなくてもできましたが、もしそれがすべきだとすれば、おそらく何か間違っていました。編集のために申し訳ありません。 –

+0

ありがとうございました:)安心して働いた! – Erik

25

これは、グローバルの書式設定を変更せずに、一時IsoDateTimeConverterインスタンスでもを行うことができます。

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

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

+4

受け入れられた答えよりずっと簡単です – FastTrack

+0

しかし、それはスペース文字がどこにあるかを示しています:( – DARKGuy

+1

多くの場所で同じクラスのオブジェクトをシリアライズしているなら、受け入れられた答えはこれよりも優れています –

8

も利用可能シリアライザ設定のオーバーロードのいずれかを使用します。タイプを取って

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" }); 

オーバーロードでも使用可能ですが。

+0

完璧な素晴らしいトリック – user6628729

+0

私はupvote then ;;) – Matt

+0

FYI私はあなたが 'yyyy-MM-ddTHH:mm:ssZ'を意味すると思う。 – Neek

23

あなたは、このアプローチを使用することができます。

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

+0

base.DateTimeFormat = format; – SoliQuiD

+0

これは理解しやすく、拡張性が高いので、これは最高の答えです。 –

+1

これは私にとってはうまくいかない - 'JsonConverterAttribute 'に2つの引数を取るコンストラクタが含まれていない' –

関連する問題