无法通过 GET 反序列化数组
Posted
技术标签:
【中文标题】无法通过 GET 反序列化数组【英文标题】:Unable to deserialize array via GET 【发布时间】:2014-09-10 00:49:48 【问题描述】:我正在使用 Kendo UI 的 DataSource 将排序信息发送到我的 ServiceStack 服务。我知道这个has been addressed 如果您使用的是POST
,但我想坚持RESTful 设计,所以请求动词需要是GET
。我正在使用这个 sn-p 进行测试:
var dataSource = new kendo.data.DataSource(
serverSorting: true,
sort: [ field: "ProductName", dir: "desc" ,
field: "Category", dir: "asc"],
serverPaging: true,
page: 2,
pageSize: 5,
transport:
read:
url: "/products",
dataType: "json",
contentType: "application/json",
dataType: "jsonp"
,
parameterMap: function (data, type)
//return kendo.stringify(data);
//return JSON.stringify(data);
//return $.param(data, true);
//data.sort = kendo.stringify(data.sort);
return data;
);
dataSource.fetch(function ()
console.log(dataSource.view());
);
排序参数变成一个锯齿状数组,如:
sort[0][field]: ProductName
sort[0][dir]: desc
sort[1][field]: Category
sort[1][dir]: asc
我的请求 DTO 是:
public class SortTerm
public string field get; set;
public string dir get; set;
public class KendoQuery
public List<SortTerm> Sort get; set;
public int Skip get; set;
public int Take get; set;
public int Page get; set;
public int PageSize get; set;
所有简单的参数都被反序列化了,但是我到底如何才能在客户端或服务器端转换 Sort
属性以使其正确填充?
请注意,我在 parameterMap
函数中尝试了各种序列化技术,但我完全被难住了。
编辑
所以这一切都归结为:当 jQuery 仔细地将我的请求重新排列成锯齿状数组时,如何通过 $.get() 将对象数组传递给 ServiceStack 服务?这有点像请求过滤器,但我不得不想象它之前已经解决了 **GET**
请求。
【问题讨论】:
【参考方案1】:您不能将复杂的数据结构(例如锯齿状排序数组的数据结构)与使用标准技术的 GET
请求一起使用,因为 JSON GET
请求仅支持简单变量,因为这些变量可以转换为查询字符串中的请求参数.因此,对于简单参数 ?Page=2&PageSize=5 ...
,请求将正确形成,但对于 sort[0][field]
,这不能指定为查询字符串请求参数。
但是,如果您在哪里使用datasource.transport.parameterMap
对搜索条件对象进行字符串化,以便可以将其作为参数传递,然后在服务器上进行转换,则可以解决此问题。
parameterMap: function (data, type)
// Convert the search criteria to a JSON string and store it on value sortJson
data.sortJson = JSON.stringify(data.sort);
// Remove the sort value, as this will be provided by sortJson
delete data.sort;
// Return the data
return data
在服务器上,您需要处理将 JSON 字符串转换为 List<SortTerm>
:
public class KendoQuery
List<SortTerm> sort;
public List<SortTerm> Sort
get
// Handles deserialising the SortJson value
if(sort == null)
sort = ServiceStack.JsonSerializer.DeserializeFromString<List<SortTerm>>(SortJson);
return sort;
public string SortJson get; set;
public int Skip get; set;
public int Take get; set;
public int Page get; set;
public int PageSize get; set;
我希望这会有所帮助。
【讨论】:
正如你所说,我想出来的总体原因是 GET 无法合理地传递复杂的数据结构。虽然我说客户端或服务器端修复都可以,但我更喜欢服务器端来保持客户端代码干净,并且与后端无关。我已经在下面的答案中发布了我的代码。 @jklemmack 是的,尽可能保持客户端清洁是合理的,因此您的解决方案看起来也很合适(+1)。【参考方案2】:Scott 上面的答案是正确的,但这是我更以服务器为中心的解决方案。基本上,我从查询字符串中手动重建 SortTerm
对象。这可以扩展到其他特定于 Kendo 的参数,例如过滤器和组。
客户端代码:
<html>
<head>
<meta charset="utf-8">
<title>Kendo UI Snippet</title>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.1.528/js/kendo.all.min.js"></script>
</head>
<body>
<script>
var dataSource = new kendo.data.DataSource(
serverSorting: true,
sort: [ field: "ProductName", dir: "desc" ,
field: "Category", dir: "asc" ],
serverPaging: true,
page: 2,
pageSize: 5,
transport:
read:
url: "/products",
dataType: "json"
);
dataSource.fetch(function ()
console.log(dataSource.view());
);
</script>
</body>
</html>
服务器代码(在 AppHost 实现中):
this.GlobalRequestFilters.Add((req, resp, dto) =>
if (dto is KendoQueryBase)
KendoQueryBase qb = dto as KendoQueryBase;
if (qb.Sort == null) qb.Sort = new List<SortTerm>();
Dictionary<string, string> qs = req.QueryString.ToDictionary();
var i = 0;
while (qs.ContainsKey("sort[0][field]".Fmt(i)))
qb.Sort.Add(new SortTerm()
field = qs["sort[0][field]".Fmt(i)],
dir = qs["sort[0][dir]".Fmt(i)]
);
i++;
);
【讨论】:
以上是关于无法通过 GET 反序列化数组的主要内容,如果未能解决你的问题,请参考以下文章
使用 Unity JsonUtility 反序列化 JSON 数组无法获取序列化值
使用JSON.NET反序列化json - 无法反序列化,因为类型需要一个JSON数组c#
无法将 JSON 数组(例如 [1,2,3])反序列化为类型 ' ',因为类型需要 JSON 对象(例如 "name":"value")才能正确反序列化
无法将 JSON 数组(例如 [1,2,3])反序列化为类型 ' ',因为类型需要 JSON 对象(例如 "name":"value")才能正确反序列化