ASP.NET Web API-取代JsonFormatter新選擇-招喚JilFormatter
ASP.NET Web API一開始就以JSON.NET來取代JavaScriptSerializer以完成世代交替,JSON.NET的表現一直是中規中矩,以我的認知他是求穩。ASP.NET Web API採用Formatter的設計方式,預設有JsonFormatter與XmlFormatter,在求快的過程,如同頭文字D的86,換上一顆新F1引擎是最快的方式,我們來替ASP.NET Web API安裝一顆JilFormatter的高速引擎。
Jil Media-Type Formatter
// Ref: https://github.com/bmbsqd/jil-mediaformatter // Ref: http://blog.developers.ba/replace-json-net-jil-json-serializer-asp-net-web-api/ public class JilFormatter : MediaTypeFormatter { private static readonly MediaTypeHeaderValue applicationJsonMediaType = new MediaTypeHeaderValue("application/json"); private static readonly MediaTypeHeaderValue textJsonMediaType = new MediaTypeHeaderValue("text/json"); private static readonly Task<bool> done = Task.FromResult(true); private readonly Options options; public JilFormatter(Options options) { this.options = options; SupportedMediaTypes.Add(applicationJsonMediaType); SupportedMediaTypes.Add(textJsonMediaType); SupportedEncodings.Add(new UTF8Encoding(false, true)); SupportedEncodings.Add(new UnicodeEncoding(false, true, true)); } public JilFormatter() : this( GetDefaultOptions() ) { } private static Options GetDefaultOptions() { return new Options(dateFormat: DateTimeFormat.ISO8601); } public override bool CanReadType(Type type) { if (type == null) { throw new ArgumentNullException("type"); } return true; } public override bool CanWriteType(Type type) { if (type == null) { throw new ArgumentNullException("type"); } return true; } public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger) { var reader = new StreamReader(readStream); var deserialize = TypedDeserializers.GetTyped(type); var result = deserialize(reader, options); return Task.FromResult(result); } public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext) { var writer = new StreamWriter(writeStream); JSON.Serialize(value, writer, options); writer.Flush(); return done; } } static class TypedDeserializers { private static readonly ConcurrentDictionary<Type, Func<TextReader, Options, object>> methods; private static readonly MethodInfo method = typeof(JSON).GetMethod("Deserialize", new[] { typeof(TextReader), typeof(Options) }); static TypedDeserializers() { methods = new ConcurrentDictionary<Type, Func<TextReader, Options, object>>(); } public static Func<TextReader, Options, object> GetTyped(Type type) { return methods.GetOrAdd(type, CreateDelegate); } private static Func<TextReader, Options, object> CreateDelegate(Type type) { return (Func<TextReader, Options, object>)method .MakeGenericMethod(type) .CreateDelegate(typeof(Func<TextReader, Options, object>)); } }
這樣我們就製作好新的JilFormatter。
安裝JilFormatter引擎
開啟WebApiConfig.cs組態檔,將JilFormatter安裝進ASP.NET Web API之中。
// Replace Jil config.Formatters.Remove(config.Formatters.JsonFormatter); config.Formatters.Remove(config.Formatters.XmlFormatter); config.Formatters.Add(new JilFormatter());
這裡我是把ASP.NET Web API兩個預設JsonFormatter與XmlFormatter給移除,並把新的JilFormatter結設定進去。如果你不想一次JsonFormatter與XmlFormatter都給移除,那麼也可以用Insert()的方式來設置:
config.Formatters.RemoveAt(0); config.Formatters.Insert(0, new JilFormatter());
這樣的意思是把index 0的JsonFormatter給移除,並把新的JilFormatter插入至index 0的位置,也就是第一順位使用JilFormatter來執行(反)序列化。
public IHttpActionResult Get() { var dt = DateTime.Now; return Ok(dt); }
進行簡單測試,確認序列化日期是正常的。
public IHttpActionResult Get() { ListbigList = new User().GenSimData(); return Ok(bigList); }
透過之前的評比程式取得2萬筆資料進行序列化測試。再提醒一次,Jil的序列化會進行UTC時區處理,所以資料接收端要進行時區修正的動作。
小結
針對ASP.NET MVC(JsonResult)/Web API的效能提升,換上一顆高效的JSON(反)序列化處理引擎,尤其是ASP.NET Web API本身就是專門針對JSON格式所設計的Framework,在效能改善上有著非常正能量的幫助。
Github Sample Source code:KK.JilTest
你好, 我試過有bug, Master-Detail 資料表會只出現Detail的資料
回覆刪除嗯,這套我們很用久了,沒碰到你說的狀況也...
刪除