2013-09-05 33 views
58

Tôi đang phát triển API để hiển thị một số dữ liệu bằng ASP.NET Web API.Chỉ định định dạng Ngày giờ tùy chỉnh khi tuần tự hóa với Json.Net

Trong một trong các API, khách hàng muốn chúng tôi hiển thị ngày ở định dạng dd-yyyy-dd. Tôi không muốn thay đổi cài đặt chung (ví dụ: GlobalConfiguration.Configuration.Formatters.JsonFormatter) vì điều đó rất cụ thể cho khách hàng này. Và tôi phát triển điều đó trong một giải pháp cho nhiều khách hàng.

Một trong những giải pháp mà tôi có thể nghĩ đến là tạo ra một tùy chỉnh Json chuyển đổi và sau đó đưa đến tài sản tôi cần phải làm những định dạng tùy chỉnh

ví dụ

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

Chỉ cần tự hỏi liệu có cách nào khác dễ dàng thực hiện điều đó không.

+8

Đối với những gì nó có đáng giá, các API dành cho khả năng đọc của máy tính, không phải khả năng đọc của người dùng, vì vậy tốt hơn là nên gắn vào một định dạng ngày được chỉ định duy nhất, chẳng hạn như [ISO 8601] (http://xkcd.com/1179/). Nếu khách hàng trực tiếp hiển thị kết quả API cho người dùng hoặc viết mã phân tích cú pháp ngày của riêng họ cho API, thì họ đang làm sai. Việc định dạng ngày hiển thị phải được để lại ở lớp giao diện người dùng trên cùng. – MCattle

Trả lời

91

Bạn đang đi đúng hướng. Vì bạn đã nói rằng bạn không thể sửa đổi cài đặt chung, thì điều tốt nhất tiếp theo là áp dụng thuộc tính JsonConverter trên cơ sở khi cần thiết, như bạn đã đề xuất. Hóa ra Json.Net đã tích hợp sẵn IsoDateTimeConverter cho phép bạn chỉ định định dạng ngày tháng. Thật không may, bạn không thể đặt định dạng thông qua thuộc tính JsonConverter, vì đối số duy nhất của thuộc tính là một loại. Tuy nhiên, có một giải pháp đơn giản: phân lớp IsoDateTimeConverter, sau đó chỉ định định dạng ngày trong hàm tạo của lớp con. Áp dụng thuộc tính JsonConverter khi cần, chỉ định công cụ chuyển đổi tùy chỉnh của bạn và bạn đã sẵn sàng sử dụng. Đây là toàn bộ mã cần thiết:

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

Nếu bạn không nhớ có thời gian ở đó, bạn thậm chí không cần phải phân lớp IsoDateTimeConverter. Định dạng ngày mặc định của nó là yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK (như đã thấy trong source code).

+0

@Koen Zomers - Dấu ngoặc kép đơn bạn xóa khỏi định dạng ngày của tôi về mặt kỹ thuật LÀ đúng, mặc dù chúng không thực sự cần thiết ở đây. Xem _Literal String Delimiters_ trong [tài liệu cho các chuỗi định dạng ngày và thời gian tùy chỉnh] (http://msdn.microsoft.com/en-us/library/8kb3ddd4 (v = vs.110) .aspx). Tuy nhiên, định dạng mà tôi trích dẫn là định dạng mặc định cho 'IsonDateTimeConverter' được lấy trực tiếp từ [mã nguồn Json.Net] (http://json.codeplex.com/SourceControl/latest#trunk/Src/Newtonsoft.Json/ Converters/IsoDateTimeConverter.cs); do đó tôi hoàn nguyên chỉnh sửa của bạn về điều đó. –

+0

nó đã không hoạt động ở đây với các dấu ngoặc kép và nó đã làm mà không có chúng, nhưng nếu bạn nói nó nên, tôi có thể đã làm điều gì đó sai trái. Xin lỗi vì chỉnh sửa. –

+0

Cảm ơn bạn rất nhiều :) đã làm việc một cách dễ dàng! – Erik

25

Nó cũng có thể được thực hiện với một trường hợp tạm IsoDateTimeConverter, mà không thay đổi các thiết lập định dạng toàn cầu:

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

này sử dụng quá tải mà phải mất một lập luận params JsonConverter[].

+4

Đơn giản hơn câu trả lời được chấp nhận – FastTrack

+0

Tuy nhiên, nó hiển thị chữ T trong đó ký tự khoảng trắng là: ( – DARKGuy

+1

Nếu bạn đang nối tiếp cùng một đối tượng lớp ở nhiều nơi, thì câu trả lời được chấp nhận tốt hơn –

8

Cũng có sẵn bằng một trong những thiết lập serializer quá tải:

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

Hoặc

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

quá tải tham gia một loại cũng có sẵn.

+0

mẹo hoàn hảo và tuyệt vời này – user6628729

+0

tôi một upvote sau đó!;) – Matt

+0

FYI Tôi nghĩ rằng bạn có nghĩa là 'yyyy-MM-ddTHH: mm: ssZ' .. 24 giờ đồng hồ trên giờ. – Neek

23

Bạn có thể sử dụng phương pháp này:

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

Và sử dụng nó theo cách này:

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

Chuỗi DateTimeFormat sử dụng chuỗi cú pháp định dạng NET mô tả ở đây: https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings

+0

base.DateTimeFormat = format; – SoliQuiD

+0

Đây là câu trả lời hay nhất vì nó dễ hiểu và dễ mở rộng. –

+1

Điều này không hiệu quả đối với tôi - tôi nhận được ''JsonConverterAttribute' không chứa một hàm tạo có 2 đối số' –

Các vấn đề liên quan