【问题标题】:DataContractJsonSerializer produces list of hashes instead of hashDataContractJsonSerializer 生成哈希列表而不是哈希
【发布时间】:2010-03-26 19:59:47
【问题描述】:

我希望得到一个 Dictionary 形式的对象:

var dict = new Dictionary<string,string>()
{
    {"blah", "bob"},
    {"blahagain", "bob"}
};

以如下形式序列化成JSON:

{ "blah": "bob", "blahagain": "bob" }

不是

[ { "key": "blah", "value": "bob" }, { "key": "blahagain", "value": "bob"}]

对于序列化集合的一般尝试似乎是一个怪物的原因是什么?

DataContractJsonSerializer 使用 ISerializable 接口来产生这个东西。在我看来,好像有人从 ISerializable 中提取了 XML 输出,并把它弄坏了。

有没有办法覆盖 .Net 在这里使用的默认序列化?我可以从 Dictionary 派生并覆盖序列化方法吗?

发布以听取人们可能提出的任何警告或建议。

【问题讨论】:

    标签: c# json .net-3.5 datacontract


    【解决方案1】:

    好吧,我决定回避 Dictionary 对象的 DataContract 序列化。

    我在根对象中创建了两个虚拟方法。

    public virtual void prepareForSerialization();
    public virtual void postDeserialize();
    

    然后为我的类的每个字典属性指定字符串 DataMember 类属性。字符串被序列化,字典不再直接序列化。

    [DataMember]
    public string dictionaryString;
    public Dictionary<int, string> dict;
    

    然后,当我的代码调用 serialize 时,它​​还首先调用 prepareForSerialization。

    public override void prepareForSerialization() { 
        base.prepareForSerialization();
    }
    
    public override void postDeSerialize() {
        base.postDeSerialize();
    }
    

    然后,带有 Dictionary 成员的派生类将为 Dictionary 调用我自己的序列化程序。

    注意:这是一个适合我目的的简单序列化。 YMMV。 Javascript 归功于另一个 stackoverfow 帖子。忘记哪一个了。

    /// <summary>
    /// Extension methods needed to implement Javascript dates for C#
    /// </summary>
    public static class MyExtensions{
        public static double JavascriptTicks(this DateTime dt) {
            DateTime d1 = new DateTime(1970, 1, 1);
            DateTime d2 = dt.ToUniversalTime();
            TimeSpan ts = new TimeSpan(d2.Ticks - d1.Ticks);
            return ts.TotalMilliseconds;
        }        
    }
    /// <summary>
    /// Serialize a single value
    /// </summary>
    /// <param name="o">An object to serialize</param>
    /// <returns>A JSON string of the value</returns>
    if (o is string) {
        return string.Format("\"{0}\"", o);
    } else if (o is DateTime) {
        return string.Format("new Date({0})", ((DateTime)o).JavascriptTicks()); ;
    } else if(o.GetType().IsValueType) {
        return o.ToString();
    } else {
        //Here you want a check of the form if is IMySerializer, then call your prepare before
        //using the .Net one.
        DataContractJsonSerializer json = new DataContractJsonSerializer(o.GetType());
        using(MemoryStream ms = new MemoryStream())
        using (StreamReader sr = new StreamReader(ms)) {
            json.WriteObject(ms, o);
            ms.Position = 0;
            return sr.ReadToEnd();
        }
    }
    
    /// <summary>
    /// Serializes a List object into JSON
    /// </summary>
    /// <param name="list">The IList interface into the List</param>
    /// <returns>A JSON string of the list</returns>
    public string SerializeList(IList list) {
        string result = null;
        if (list != null) {
            IEnumerator it = list.GetEnumerator();
            StringBuilder sb = new StringBuilder();
            long len = list.Count;
            sb.Append("[");
            while (it.MoveNext()) {
                if (it.Current is IList) {
                    sb.Append(SerializeList((IList)it.Current));
                } else if (it.Current is IDictionary) {
                    sb.Append(SerializeDictionary((IDictionary)it.Current));
                } else {
                    sb.Append(SerializeValue(it.Current));
                }
                --len;
                if (len > 0) sb.Append(",");
            }
            sb.Append("]");
            result = sb.ToString();
        }
        return result;
    }
    /// <summary>
    /// Returns a stringified key of the object
    /// </summary>
    /// <param name="o">The key value</param>
    /// <returns></returns>
    public string SerializeKey(object o) {
        return string.Format("\"{0}\"", o); 
    }
    /// <summary>
    /// Serializes a dictionary into JSON
    /// </summary>
    /// <param name="dict">The IDictionary interface into the Dictionary</param>
    /// <returns>A JSON string of the Dictionary</returns>
    public string SerializeDictionary(IDictionary dict) {
        string result = null;
        if (dict != null) {
            IDictionaryEnumerator it = dict.GetEnumerator();
            StringBuilder sb = new StringBuilder();
            long len = dict.Count;
            sb.Append("{");
            while (it.MoveNext()) {
                sb.Append(SerializeKey(it.Key));
                sb.Append(":");
                if (it.Value is IList) {
                    sb.Append(SerializeList((IList)it.Value));
                } else if (it.Value is IDictionary) {
                    sb.Append(SerializeDictionary((IDictionary)it.Value));
                } else {
                    sb.Append(SerializeValue(it.Value));
                }
                --len;
                if (len > 0) sb.Append(",");
            }
            sb.Append("}");
            result = sb.ToString();
        }
        return result;
    }   
    

    【讨论】:

    • 修复了值序列化的错误。
    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 2014-12-22
    • 2011-12-16
    • 2013-03-21
    相关资源
    最近更新 更多