【问题标题】:.NET: Can I use DataContractJsonSerializer to serialize to a JSON associative array?.NET:我可以使用 DataContractJsonSerializer 序列化为 JSON 关联数组吗?
【发布时间】:2010-05-13 12:20:30
【问题描述】:

当使用DataContractJsonSerializer 序列化字典时,像这样:

[CollectionDataContract]
public class Clazz : Dictionary<String,String> {}

    ....

    var c1 = new Clazz();
    c1["Red"] = "Rosso";
    c1["Blue"] = "Blu";
    c1["Green"] = "Verde";

使用此代码序列化 c1:

    var dcjs = new DataContractJsonSerializer(c1.GetType());
    var json = new Func<String>(() =>
        {
            using (var ms = new System.IO.MemoryStream())
            {
                    dcjs.WriteObject(ms, c1);
                    return Encoding.ASCII.GetString(ms.ToArray());
            }
        })();

...产生这个 JSON:

[{"Key":"Red","Value":"Rosso"},
 {"Key":"Blue","Value":"Blu"},
 {"Key":"Green","Value":"Verde"}]

但是,这不是 Javascript 关联数组。如果我在javascript中做相应的事情:生成一个字典然后序列化它,就像这样:

var a = {};
a["Red"] = "Rosso";
a["Blue"] = "Blu";
a["Green"] = "Verde";

// use utility class from http://www.JSON.org/json2.js
var json = JSON.stringify(a);

结果是:

{"Red":"Rosso","Blue":"Blu","Green":"Verde"}

如何让 DCJS 为字典生成或使用与 JSON2.js 兼容的序列化字符串?


我从 ASP.NET 知道 JavaScriptSerializer。不确定它是否对 WCF 非常友好。是否尊重 DataMember、DataContract 属性?

【问题讨论】:

  • JavaScriptSerializer 不知道 DataMember 和 DataContract,所以恐怕没有尊重。

标签: .net asp.net wcf json


【解决方案1】:

它正在做的事情是完全明智的,它生成的 JSON 是 JSON 中 .net 字典的合理表示。如果你想要你描述的 JSON 输出,你需要序列化一个像

这样的类
public class ColourThingy
{
      public string Red {get;set;}
      public string Blue {get;set;}
      public string Green {get;set;}
}
ColourThingy MyColourThingy = new ColourThingy();
MyColourThingy.Red = "Rosso";
...

请记住,JavaScript 关联数组并不是真正的数组,您只是在利用 object["key"] 是引用 object.key 的另一种方式这一事实。因此,当它将 .net 字典序列化为 JSON 时,它会生成一个键/值对对象数组,正如您所期望的那样。

【讨论】:

  • 我知道 JavaScript assoc 数组不是数组。它们是字典。我希望 DataContractJsonSerializer 能够使用 JSON2.js 生成的形式反序列化为 .NET 字典。反之亦然。我知道 DCJS 生成的 JSON 是字典内容的忠实表示。我认为它是“合理的”,因为它不能被 JSON.js 反序列化成字典。一个 4 行 js 函数可以纠正这个问题,但是。 . . DCJS 最好首先做正确的(可互操作的)事情。
  • 问题是 JS assoc 数组不是字典,它们只是对象。它只是语言的一个特性,您可以在字典/关联数组类型语法中引用对象属性,例如object["property"] 以及 object.property。如果您要以您描述的方式序列化 .net 字典,则需要对字典对象进行特殊封装,并对每个其他对象进行不同的处理,这意味着如果您创建自己的与字典相同的类,它将序列化一种方式,但如果您使用真正的 dict,它会以另一种方式进行
  • 根据您的观点,JS 对象是或不是字典。问题是,.NET 中的 JSON 序列化框架是否需要为每个 JS 对象预定义类型?两面我都看得出来,但是在处理 JS 时我更喜欢更灵活的方法,因为 没有办法在 JS 中定义一个固定的类型。每个对象都可以扩展,每个属性列表都是动态的。因此,要求正式的 .NET 类型与动态 JS 对象交互是不自然和人为的。字典是有道理的。 (我没有考虑过新的 .NET 4.0 动态类型。)
  • 我想你有点让我明白了“.NET 中的 JSON 序列化框架是否需要为每个 JS 对象预定义类型”答案是否定的,它遵循一般模式并创建JSON 格式的 JS 对象尽可能接近 .Net 对象。 .Net 字典有一个作为集合的键属性和一个作为集合的值属性,并且序列化它会生成一个 JS 对象,其中键属性是数组,值属性是数组。
【解决方案2】:

【讨论】:

  • 这不是错误。如果你需要这样的序列化,你可以使用 JavaScriptSerializer。 DataContractJsonSerializer 旨在支持类型的键,而不仅仅是字符串。键值对数组是序列化字典的一种完全合法的方式。
  • 我想每个人都有权发表意见。正如您所说,它似乎“完全合法”,除非它应该是 JSON 序列化程序,在这种情况下它会失败:它不会与 #1 JSON 反序列化库进行往返。如果它不能与 JSON 一起使用,我看不出 MS 如何将其称为 JSON 序列化程序。我理解通用性的必要性,但是当键是字符串时,有一个非常明显的优化路径。而且,很容易使用属性来开启这种优化。即便如此,MS 仍以“无法修复”为由拒绝了该错误。他们评论说他们将来可能会增强序列化程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-06
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 1970-01-01
相关资源
最近更新 更多