听闻Jil JSON序列化的速度相当快,所以决定做个简单测试。编码平台是Visual Studio 2013,浏览器是Firefox 39.0.3。
后台App启动时,创建了一个有100万条记录的List对象。有一个API方法返回这100万条记录。时间计时在前台,所以,总的耗时不只后台序列化时间,还包括将这100万条记录传输到前台并反序列化的时间。虽然不是纯粹的序列化时间,但能反应出二者。
下面是几次测试耗时记录:
测试次序 | 原生JSON耗时(秒) | Jil JSON耗时(秒) |
---|---|---|
1 | 6.249 | 4.239 |
2 | 5.911 | 3.902 |
3 | 6.037 | 3.854 |
4 | 5.997 | 3.862 |
5 | 6.033 | 4.419 |
6 | 5.982 | 3.717 |
7 | 5.966 | 3.721 |
8 | 6.045 | 2.984 |
9 | 6.568 | 3.673 |
10 | 5.945 | 3.667 |
11 | 6.018 | 3.169 |
12 | 6.033 | 3.782 |
平均 | 6.065 | 3.749 |
Jil要比原生的快61.8%,值得推荐。
注册使用Jil的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace ProductsApp
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API 配置和服务
config.Formatters.RemoveAt(0);
config.Formatters.Insert(0, new JilFormatter());
// Web API 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
注释掉代码中的这两行
config.Formatters.RemoveAt(0);
config.Formatters.Insert(0, new JilFormatter());
即可以恢复原生JSON序列化。其中的JilFormatter如下:
using System;
using System.IO;
using System.Net;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Jil;
namespace ProductsApp
{
public class JilFormatter : MediaTypeFormatter
{
private readonly Options _jilOptions;
//private MethodInfo _method;
public JilFormatter()
{
//要序列化的时间格式
_jilOptions = new Options(dateFormat: DateTimeFormat.ISO8601);
//媒体类型
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
//加入 UTF8Encoding 编码
SupportedEncodings.Add(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true));
//加入 UnicodeEncoding 编码
SupportedEncodings.Add(new UnicodeEncoding(bigEndian: false, byteOrderMark: true, throwOnInvalidBytes: true));
}
//判断是否反序列化类型
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, System.Net.Http.HttpContent content, IFormatterLogger formatterLogger)
{
return Task.FromResult(DeserializeFromStream(type, readStream));
}
private object DeserializeFromStream(Type type, Stream readStream)
{
try
{
using (var reader = new StreamReader(readStream))
{
return JSON.Deserialize(reader, type, _jilOptions);
}
}
catch
{
return null;
}
}
// 异步序列化一个指定类型的对象。
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, System.Net.Http.HttpContent content, TransportContext transportContext)
{
var streamWriter = new StreamWriter(writeStream);
JSON.Serialize(value, streamWriter, _jilOptions);
streamWriter.Flush();
return Task.FromResult(writeStream);
}
}
}
这段代码也是从网上直接抄来的,只另注释了一行未使用变量定义,哈哈。
下面是前台代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Product App</title>
<script src="Scripts/jquery-3.1.0.min.js"></script>
</head>
<body>
<div>
<p id="beginTime" />
<p id="endTime" />
<h2>All Products</h2>
<ul id="products" />
</div>
<div>
<h2>Search by ID</h2>
<input type="text" id="prodId" size="5" />
<input type="button" value="统计时间" onclick="calcTime();" />
<input type="button" value="Search" onclick="find();" />
<p id="product" />
</div>
<script type="text/javascript">
var uri = 'api/products';
$(document).ready(function () {
Send an AJAX request
//$.getJSON(uri).done(function (data) {
// // On success, 'data' contains a list of products.
// $.each(data, function (key, item) {
// // Add a list item for the product.
// $('<li>', { text: formatItem(item) }).appendTo($('#products'));
// });
//});
});
function formatItem(item) {
return item.Name + ': $' + item.Price;
}
function find() {
var id = $('#prodId').val();
$.getJSON(uri + '/' + id)
.done(function (data) {
$('#product').text(formatItem(data));
})
.fail(function (jqXHR, textStatus, err) {
$('#product').text('Error: ' + err);
});
}
function getTimeMi() {
var d = new Date();
return d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + "." + d.getMilliseconds();
}
function calcTime() {
$('#beginTime').text(getTimeMi());
$.getJSON(uri).done(function (data) {
$('#endTime').text(getTimeMi());
});
}
</script>
</body>
</html>