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()
{
List bigList = 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的資料
回覆刪除嗯,這套我們很用久了,沒碰到你說的狀況也...
刪除