2013-09-05 13 views
58

Zajmuję się tworzeniem interfejsu API w celu ujawnienia niektórych danych przy użyciu interfejsu ASP.NET Web API.Określanie niestandardowego formatu DateTime podczas serializacji za pomocą Json.Net

W jednym z interfejsów API klient chce, abyśmy ujawnili datę w formacie rrrr-MM-dd. Nie chcę zmieniać ustawień globalnych (np. GlobalConfiguration.Configuration.Formatters.JsonFormatter), ponieważ jest to bardzo specyficzne dla tego klienta. I rozwijam to w rozwiązaniu dla wielu klientów.

Jednym z roztworem, że mogę myśleć jest stworzenie własnego konwertera JSON, a następnie umieścić że do właściwości muszę zrobić formatowanie niestandardowej

np

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

Zastanawiam się, czy istnieje inny łatwy sposób na zrobienie tego.

+8

Za to, co Warto, interfejsy API są przeznaczone do odczytu komputerowego, a nie czytelności dla użytkownika, więc lepiej trzymać się jednego określonego formatu daty, takiego jak [ISO 8601] (http://xkcd.com/1179/). Jeśli klient bezpośrednio wyświetla wynik interfejsu API użytkownikowi lub pisze własny kod analizujący datę dla interfejsu API, robi to źle. Formatowanie daty wyświetlania należy pozostawić do najwyższej warstwy interfejsu użytkownika. – MCattle

Odpowiedz

91

Jesteś na dobrej drodze. Ponieważ powiedziałeś, że nie możesz modyfikować ustawień globalnych, najlepszą rzeczą jest zastosowanie atrybutu JsonConverter w razie potrzeby, zgodnie z sugestiami. Okazuje się, że Json.Net ma już wbudowany IsoDateTimeConverter, który pozwala określić format daty. Niestety, nie można ustawić formatu za pomocą atrybutu JsonConverter, ponieważ jedynym argumentem atrybutu jest typ. Istnieje jednak proste rozwiązanie: podklasa IsoDateTimeConverter, następnie określ format daty w konstruktorze podklasy. Zastosuj atrybut JsonConverter w razie potrzeby, określając swój niestandardowy konwerter i jesteś gotowy do pracy. Oto całość kodu potrzebne:

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

Jeśli nie przeszkadza mieć czas tam również, że nie trzeba nawet podklasy IsoDateTimeConverter. Jego domyślny format daty to yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK (jak widać w source code).

+0

@Koen Zomers - Pojedyncze cytaty usunięte z moich formatów daty są Z technicznego punktu widzenia SĄ poprawne, chociaż nie są tutaj bezwzględnie konieczne. Zobacz _Literal String Delimiters_ w [dokumentacji dla łańcuchów formatu daty niestandardowej i formatu czasu] (http://msdn.microsoft.com/en-us/library/8kb3ddd4 (v = vs.110) .aspx). Jednak format podany jako format domyślny dla 'IsonDateTimeConverter' został pobrany bezpośrednio z [kodu źródłowego Json.Net] (http://json.codeplex.com/SourceControl/latest#trunk/Src/Newtonsoft.Json/ Konwertery/IsoDateTimeConverter.cs); dlatego cofam twoją edycję na ten temat. –

+0

to nie działało tutaj z cytatami i stało się bez nich, ale jeśli powiesz, że powinno, prawdopodobnie zrobiłem coś złego. Przepraszamy za edycję. –

+0

Dziękuję bardzo :) pracował z łatwością! – Erik

25

To może być również wykonane z instancji temp IsoDateTimeConverter, bez zmiany ustawień formatowania globalne:

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

używa przeciążenie, że trwa params JsonConverter[] argument.

+4

Znacznie prostsza niż przyjęta odpowiedź – FastTrack

+0

Jednak pokazuje T, gdzie jest spacja :( – DARKGuy

+1

Jeśli serializujesz obiekt tej samej klasy w wielu miejscach, to zaakceptowana odpowiedź jest lepsza niż ta –

8

Również dostępne za pomocą jednego z ustawień serializer przeciążeń:

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

Albo

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

Przeciążenia biorący typu są również dostępne.

+0

doskonała i świetna sztuczka. – user6628729

+0

ja upto to wtedy!;) – Matt

+0

FYI Myślę, że masz na myśli 'yyyy-MM-ddTHH: mm: ssZ' .. 24 godzinny zegar na godziny. – Neek

23

Można użyć tej metody:

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

i używać go w ten sposób:

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

Ciąg DateTimeFormat używa ciąg składni formatu NET opisaną tutaj: https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings

+0

base.DateTimeFormat = format; – SoliQuiD

+0

To jest najlepsza odpowiedź, ponieważ jest łatwa do zrozumienia i bardzo rozszerzalna. –

+1

To nie działa dla mnie - otrzymuję "JsonConverterAttribute" nie zawiera konstruktora, który ma 2 argumenty' –

Powiązane problemy