使用JavaScriptSerializer反序列化JSON

4
我使用以下函数构建导航树并将其结构保存在数组中。
function parseTree(html) {
   var nodes = [];
   html.parent().children("div").each(function () {
      var subtree = $(this).children("div");
      var item = $(this).find(">span");
      if (subtree.size() > 0)
          nodes.push([item.attr("data-pId"), item.attr("data-id"), parseTree(subtree)]);
      else
          nodes.push(item.attr("data-pId"), item.attr("data-id"));
  });
  return nodes;
}

然后我对数据进行序列化。
var tree = $.toJSON(parseTree($("#MyTree").children("div")));

获取这个数组。
[
    ["881150024","881150024",
        [
         "994441819","881150024",
         "214494418","881150024"
        ]
    ],
    ["-256163399","-256163399",
        [
            "977082012","-256163399",
            "-492694206","-256163399",
            [
                "1706814966","-256163399",
                    ["-26481618","-256163399"]
            ]
        ]
    ]
]

并通过ajax发送它

             $.ajax({
                url: "Editor/SerializeTree",
                type: "POST",
                data: { tree: tree },
                success: function (result) {
                    alert("OK");
                }
            });

问题:如何使用C#中的JavaScriptSerializer反序列化此JSON?

3个回答

10

这里似乎你有一个节点数组,每个节点都有一组字符串或另一个节点数组,对吧?你可以首先将其反序列化为一个 List<object>,像这样:

string treeData = "..."; // The JSON data from the POST
JavaScriptSerializer js = new JavaScriptSerializer();
List<object> tree = js.Deserialize <List<object>>(treeData);
这将把你的JSON转换成一个对象列表,但你需要手动确定每个对象是什么(如果每个对象是一个字符串或另一个List<object>)。总的来说,最好有某种类或结构来表示您为序列化器提供的数据的“模式”,但这需要比上面的方法更多的工作。在这种情况下,您需要将输入数据实际上变成一个JSON对象,而不仅仅是一个数组。假设你有这个JSON(基于上述数据):
{id: "root", children: [
  {id: "881150024"},
  {id: "881150024", children: [
    {id: "994441819"}, {id: "881150024"}]},
    {id: "-256163399"},
    {id: "-256163399", children: [            
    {id: "-492694206"},
      {id: "-256163399", children: [
        {id: "1706814966"},
        {id: "-256163399", children: [
          {id: "-26481618"}, {id: "-256163399"}]}
]}]}]}

如果你有这样一个类:

public class Node
{
  public String id;
  public List<Node> children;
}

您可以像下面这样进行操作:

string treeData = "..."; // The JSON data from the POST
JavaScriptSerializer js = new JavaScriptSerializer();
Node root = js.Deserialize<Node>(treeData);

这在代码中处理起来会更容易。


非常清晰明了!我使用了第二种解决方案。我只需要修复这一行 List<Node> root = js.Deserialize<List<Node>>(tree); 非常感谢。这是我第一次使用反序列化编写脚本 :-) - podeig

1

对于我们中的极少数仍在偶尔使用VB.Net的人:

Imports System.Web.Script.Serialization

'wsvcResponse<string> contains the following JSON object: { "foo":"bar", "foo2": { "bar2": "foobar" } }
Dim jsSerializer As New JavaScriptSerializer()
Dim jsonObject As List(Of Object) = jsSerializer.Deserialize(Of Object)(wsvcResponse)
Dim foo As String = jsonObject("foo").ToString  ' "bar"
Dim bar2 As String = jsonObject("foo2")("bar2").ToString ' "foobar"

1
真的是新手问题 - 在 Dim jsonObject As List(Of Object) 中,我应该用我创建的类替换 Object,还是只保留 Object - DeeKayy90
1
我正在使用通用的Object类(这对我来说很少见,因为我通常使用明确的类型),主要是因为我找不到更好的方法来获取Deserialize()方法转换后的结果。我的最初直觉是:".Deserialize(Of List(of string))(wsvcResposne),但我无法按预期工作。 - rainabba

1

考虑到 @_rusty 的回答。

MVC3 中可以将 JSON 数据绑定到操作中,因此您的控制器代码将非常简单。

[HttpPost]
public void SerializeTree(IList<Node> tree)
{
    // tree is deserialized JSON here
}

谢谢Alexander!我现在使用的是MVC2。当我将其更新到第3个版本时,我会尝试这个优美的解决方案。 :-) - podeig
@podeig,我不会等待 :) 并使用MvcFutures来获得所需的解决方案。它非常简单和美观,请查看此链接http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx - Alexander Beletsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接