DataContractJsonSerializer生成散列列​​表而不是散列

时间:2010-03-26 19:59:47

标签: c# json .net-3.5 datacontract

我希望形式为:

的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派生并覆盖序列化方法吗?

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

1 个答案:

答案 0 :(得分: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();
}

带有字典成员的派生类将调用我自己的字典序列化器。

注意:这是一个适合我目的的简单序列化。因人而异。 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;
}