使用JavaScriptSerializer序列化词典

显然, IDictionary被序列化为KeyValuePair对象的数组(例如, [{Key:"foo", Value:"bar"}, ...] )。 是否可以将其序列化为对象(例如, {foo:"bar"} )?

虽然我同意JavaScriptSerializer是一个垃圾,Json.Net是一个更好的选择,但有一种方法可以让JavaScriptSerializer按照你想要的方式进行序列化。 您将必须注册转换器并使用以下内容覆盖Serialize方法:

  public class KeyValuePairJsonConverter : JavaScriptConverter { public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer) { var instance = Activator.CreateInstance(type); foreach (var p in instance.GetType().GetPublicProperties()) { instance.GetType().GetProperty(p.Name).SetValue(instance, dictionary[p.Name], null); dictionary.Remove(p.Name); } foreach (var item in dictionary) (instance).Add(item.Key, item.Value); return instance; } public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) { var result = new Dictionary(); var dictionary = obj as IDictionary; foreach (var item in dictionary) result.Add(item.Key, item.Value); return result; } public override IEnumerable SupportedTypes { get { return new ReadOnlyCollection(new Type[] { typeof(your_type) }); } } } JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer(); javaScriptSerializer.RegisterConverters(new JavaScriptConverter[] { new ExpandoJsonConverter() }); jsonOfTest = javaScriptSerializer.Serialize(test); // {"x":"xvalue","y":"\/Date(1314108923000)\/"} 

希望这可以帮助!

不, JavaScriptSerializer无法实现。 有可能使用Json.NET :

 public class Bar { public Bar() { Foos = new Dictionary { { "foo", "bar" } }; } public Dictionary Foos { get; set; } } 

然后:

 var bar = new Bar(); string json = JsonConvert.SerializeObject(bar, new KeyValuePairConverter()); 

会产生所需的:

 {"Foos":{"foo":"bar"}} 

我可以用Linq Select的JavaScriptSerializer解决:

 var dictionary = new Dictionary(); var jsonOutput = new JavaScriptSerializer().Serialize(dictionary.Select(x => new { Id = x.Key, DisplayText = x.Value })); 

我能够使用JavaScriptSerializer解决它,诀窍是创建自己的转换器。 以下代码是工作代码:

 public class KeyValuePairJsonConverter : JavaScriptConverter { public override object Deserialize(IDictionary dictionary , Type type , JavaScriptSerializer serializer) { throw new InvalidOperationException("Sorry, I do serializations only."); } public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) { Dictionary result = new Dictionary(); Dictionary dictionaryInput = obj as Dictionary; if (dictionaryInput == null) { throw new InvalidOperationException("Object must be of Dictionary type."); } foreach (KeyValuePair pair in dictionaryInput) result.Add(pair.Key, pair.Value); return result; } public override IEnumerable SupportedTypes { get { return new ReadOnlyCollection(new Type[] { typeof(Dictionary) }); } } } 

这是你如何使用它:

 JavaScriptSerializer js = new JavaScriptSerializer(); js.RegisterConverters(new JavaScriptConverter[] { new KeyValuePairJsonConverter() }); Context.Response.Clear(); Context.Response.ContentType = "application/json"; Context.Response.Write(js.Serialize(myObject)); 

这是我相信Tomas的改进版本的答案。 奇迹般有效。 我们还可以添加一个ScriptIgnore属性的检查,但是好吧,自己敲门。

顺便说一下,我选择了JavaScriptSerializer,因为在我看来,第三方解决方案大部分时间都是:知名度较低,安装时间较长,经常被遗忘的预先存在,并且模糊版权状态使得它们在商业中分发风险很大。

PS:我不明白为什么我们试图将实例和实例反序列化为字典,所以我剥离了那部分。

 public class KeyValuePairJsonConverter : JavaScriptConverter { public override object Deserialize(IDictionary deserializedJSObjectDictionary, Type targetType, JavaScriptSerializer javaScriptSerializer) { Object targetTypeInstance = Activator.CreateInstance(targetType); FieldInfo[] targetTypeFields = targetType.GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo fieldInfo in targetTypeFields) fieldInfo.SetValue(targetTypeInstance, deserializedJSObjectDictionary[fieldInfo.Name]); return targetTypeInstance; } public override IDictionary Serialize(Object objectToSerialize, JavaScriptSerializer javaScriptSerializer) { IDictionary serializedObjectDictionary = new Dictionary(); FieldInfo[] objectToSerializeTypeFields = objectToSerialize.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo fieldInfo in objectToSerializeTypeFields) serializedObjectDictionary.Add(fieldInfo.Name, fieldInfo.GetValue(objectToSerialize)); return serializedObjectDictionary; } public override IEnumerable SupportedTypes { get { return new ReadOnlyCollection(new Type[] { typeof(YOURCLASSNAME) }); } } }