2016-08-30 220 views
0

我應該如何編寫這部分代碼來序列化所有後代自定義類型?NETJson,如何序列化自定義類型集合中的自定義類型

NETJson問題(https://github.com/rpgmaker/NetJSON)。

下面的代碼用於測試它。

NETJson串行執行:

class NETJsonFormatter 
{ 
    static bool Initialize() 
    { 
     NetJSON.NetJSON.IncludeFields = true; 
     NetJSON.NetJSON.IncludeTypeInformation = true; 
     return true; 
    } 

    static bool Initialized = Initialize(); 

    /// <summary> 
    /// Serializza un oggetto in un array di byte. 
    /// </summary> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    [System.Diagnostics.DebuggerStepThrough] 
    static public byte[] Serialize(object obj) 
    { 
     return Encoding.UTF8.GetBytes(NetJSON.NetJSON.Serialize(obj)); 
    } 


    /// <summary> 
    /// Trasforma un array di byte nell'oggetto originario. 
    /// </summary> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    [System.Diagnostics.DebuggerStepThrough] 
    static public object Deserialize(byte[] obj) 
    { 
     return NetJSON.NetJSON.Deserialize<object>(Encoding.UTF8.GetString(obj)); 
    } 


    /// <summary> 
    /// Deserializza un array di byte nel Type desiderato. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    static public T Deserialize<T>(byte[] obj) 
    { 
     return NetJSON.NetJSON.Deserialize<T>(Encoding.UTF8.GetString(obj)); 
    } 
} 

第一對象序列化:

[Serializable] 
public class ComplexType 
{ 
    public ComplexType() 
    { 
     this.Numero = 100; 
     this.Stringa = "Contenuto"; 
    } 
    public int Numero { get; set; } 
    public string Stringa { get; set; } 
} 

的第二個目的是序列:

[Serializable] 
public class Message_v2 : IMessage 
{ 
    public Message_v2() 
    { 
     this.Options = new List<string>(); 
     this.Arguments = new Dictionary<string, object>(); 
    } 

    public bool IsEmpty { get; set; } 

    public MessageCommand Command { get; set; } 

    public List<string> Options { get; set; } 

    /// <summary> 
    /// Gli Arguments del parser sono sempre KeyValue. Qual'ora mancasse il Value viene inserito null. 
    /// </summary> 
    public Dictionary<string, object> Arguments { get; set; } 

    /* 
    * Public methods 
    */ 

    public void AddOptions(params string[] options) 
    { 
     foreach (string option in options) 
      this.Options.Add(option); 
    } 

    public void AddArgument(string key, object value) 
    { 
     this.Arguments.Add(key, value); 
    } 

    public byte[] ToArray() 
    { 
     return NETJsonFormatter.Serialize(this); 
    } 

    public string ToXML() 
    { 
     throw new NotImplementedException(); 
    } 

    /// <summary> 
    /// For debugging purposes. 
    /// </summary> 
    /// <returns></returns> 
    public string ToJSON() 
    { 
     return Encoding.UTF8.GetString(NETJsonFormatter.Serialize(this)); 
    } 

    /* 
    * Conversions 
    */ 

    public static explicit operator Message_v2(byte[] source) 
    { 
     try 
     { 
      return NETJsonFormatter.Deserialize<Message_v2>(source); 
     } 
     catch 
     { 
      return null; 
     } 
    } 
} 

和失敗的單元測試。 第一個測試,ComplexObject上的測試通過。爲了確保數據的一致性,我使用了DeepEqual(https://github.com/jamesfoster/DeepEqual - NUGet上的'DeepEqual'),它提供了用於對象比較的.ShouldDeepEqual方法。

[TestMethod] 
public void CreateAndRetrieveMessage() 
{ 
    ComplexType complexArgument = new ComplexType(); 

     byte[] serializedComplexArgument = NETJsonFormatter.Serialize(complexArgument); 
     ComplexType deserializedComplexArgument = NETJsonFormatter.Deserialize<ComplexType>(serializedComplexArgument); 

     deserializedComplexArgument.ShouldDeepEqual(complexArgument); 

     /* ------------------------ */ 

     IMessage message = ProtocolHelper.CreateMessage(); 
     message.Command = MessageCommand.Set; 
     message.AddOptions("keys"); 
     message.AddArgument("Key1", "Contenuto"); 
     message.AddArgument("Key2", 100); 
     message.AddArgument("Key3", complexArgument); 

     // Send over the wire. 
     byte[] serialized = message.ToArray(); 

     // Get the Message sent. 
     var deserialized = ProtocolHelper.CreateMessage(serialized); 

     deserialized.ShouldDeepEqual(message); 
    } 

回答

0

wiki

詞典 - 值(對象)的支持字典,IList的,原始類型和枚舉

我覺得這是你的問題,只是試圖序列一個對象dicitionnary,它會失敗,但一個複雜類型的詞典成功...

ComplexType complexArgument = new ComplexType(); 

byte[] serializedComplexArgument = NETJsonFormatter.Serialize(complexArgument); 
ComplexType deserializedComplexArgument = NETJsonFormatter.Deserialize<ComplexType>(serializedComplexArgument); 

deserializedComplexArgument.ShouldDeepEqual(complexArgument); 


/* ------------------------ */ 

var complexTypeDictionnary = new Dictionary<string, ComplexType>(); 
complexTypeDictionnary.Add("Key3", complexArgument); 

byte[] serializedDic2 = NETJsonFormatter.Serialize(complexTypeDictionnary); 
var deserializeDictionnary2 = NETJsonFormatter.Deserialize<Dictionary<string, ComplexType>>(serializedDic2); 

deserializeDictionnary2.ShouldDeepEqual(complexTypeDictionnary); // works 


/* ------------------------ */ 

var objectDictionnary = new Dictionary<string, object>(); 
objectDictionnary.Add("Key1", "Contenuto"); 
objectDictionnary.Add("Key2", 100); 
objectDictionnary.Add("Key3", complexArgument); 

byte[] serializedDic = NETJsonFormatter.Serialize(objectDictionnary); 
var deserializeDictionnary = NETJsonFormatter.Deserialize<Dictionary<string, object>>(serializedDic); 

deserializeDictionnary.ShouldDeepEqual(objectDictionnary); // doesn't work 

編輯

我用NewtonSoft玩的JSON序列化,也許你的搜索性能改進或其他,但它有它運作良好;)

/* ------------------------ */ 

var objectDictionnary = new Dictionary<string, object>(); 
objectDictionnary.Add("Key1", "Contenuto"); 
objectDictionnary.Add("Key2", 100); 
objectDictionnary.Add("Key3", complexArgument); 


byte[] serializedDicNewton = Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(objectDictionnary)); 
var deserializeDictionnaryNewton = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(Encoding.UTF8.GetString(serializedDicNewton)); 

deserializeDictionnaryNewton.ShouldDeepEqual(objectDictionnary); // works too 
+0

這聽起來不錯。但我的問題是我的Message_v2.Arguments是動態的,我不知道或控制哪些類型的用戶選擇輸入它們。 所以我無法將Message_v2.Arguments的聲明從Dictionary 更改爲Dictionary 。 事實上,在我的單元測試中,我明確地寫了三個值,一個int,一個字符串,一個ComplexType。 – Lorenzo

+0

也許使用其他序列化程序,newtonsoft可以很好地用於這個用例,我編輯了我的文章 – Mathieu

+0

性能的改進是使用NETJson的關鍵。 其實我使用BinaryFormatter來進行序列化並通過線路發送並運行良好。我已經用NewtonSoft「玩」了Json序列化,沒有任何問題。 所以,你是對的,如果我想在Json上序列化,我會使用更強大的json序列化器,但是我使用標記「NETJson」打開了問題,並且stackoverflow.com確實響應了「你不能使用開始問題標記NETJson如果你沒有1500聲望點「。 Eh。 :( – Lorenzo

0

NETJson不正確序列化字典原因對象它是基類型,但它可以序列化很多基元(包含字節數組),所以我找到了一個解決方案(好了,現在解決方法導致我的眼睛流血看着代碼 - 但它很好用)。

類幫手NETJson

class NETJsonFormatter 
{ 
    public NETJsonFormatter() { } 

    static bool Initialize() 
    { 
     NetJSON.NetJSON.IncludeFields = true; 
     NetJSON.NetJSON.IncludeTypeInformation = true; 
     return true; 
    } 

    static bool Initialized = Initialize(); 

    /// <summary> 
    /// Serializza un oggetto in un array di byte. 
    /// </summary> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    //[System.Diagnostics.DebuggerStepThrough] 
    static public byte[] SerializeWithType(object obj) 
    { 
     return Encoding.UTF8.GetBytes(NetJSON.NetJSON.Serialize(obj.GetType(), obj)); 

    } 

    /// <summary> 
    /// Trasforma un array di byte nell'oggetto originario. 
    /// </summary> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    //[System.Diagnostics.DebuggerStepThrough] 
    static public object DeserializeWithType(Type type, byte[] obj) 
    { 
     return NetJSON.NetJSON.Deserialize(type, Encoding.UTF8.GetString(obj)); 
    } 

    static public byte[] Serialize<T>(T obj) 
    { 
     return Encoding.UTF8.GetBytes(NetJSON.NetJSON.Serialize(obj)); 
    } 

    /// <summary> 
    /// Deserializza un array di byte nel Type desiderato. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    static public T Deserialize<T>(byte[] obj) 
    { 
     return NetJSON.NetJSON.Deserialize<T>(Encoding.UTF8.GetString(obj)); 
    } 

} 

二對象序列化(這並沒有成功上已單元測試)

[Serializable] 
public class Message_v2 //: IMessage 
{ 
    public Message_v2() 
    { 
     this.Options = new List<string>(); 
     this.Arguments = new Dictionary<string, object>(); 
     this.ValuesForNETJson = new Dictionary<string, byte[]>(); 
     this.TypesForNETJson = new Dictionary<string, Type>(); 
    } 

    public bool IsEmpty { get; set; } 

    public MessageCommand Command { get; set; } 

    public List<string> Options { get; set; } 

    /// <summary> 
    /// Gli Arguments del parser sono sempre KeyValue. Qual'ora mancasse il Value viene inserito null. 
    /// </summary> 
    public Dictionary<string, object> Arguments { get; set; } 

    /// <summary> 
    /// Serializzo gli Arguments in byte array. 
    /// string - Key di Arguments[n] 
    /// byte[] - contenuto serializzato di Arguments[n] 
    /// </summary> 
    public IDictionary<string, byte[]> ValuesForNETJson { get; set; } 
    public IDictionary<string, Type> TypesForNETJson { get; set; } 

    /* 
    * Public methods 
    */ 

    public void AddOptions(params string[] options) 
    { 
     foreach (string option in options) 
      this.Options.Add(option); 
    } 

    public void AddArgument(string key, object value) 
    { 
     this.Arguments.Add(key, value); 
     this.ValuesForNETJson.Add(key, NETJsonFormatter.SerializeWithType(value)); 
     this.TypesForNETJson.Add(key, value.GetType()); 
    } 

    public byte[] ToArray() 
    { 
     //this.Arguments.ToDictionary(x => x.Value == null); 
     return NETJsonFormatter.Serialize(this); 
    } 

    /* 
    * Conversions 
    */ 

    public static explicit operator Message_v2(byte[] source) 
    { 
     try 
     { 
      Message_v2 message = NETJsonFormatter.Deserialize<Message_v2>(source); 
      int count = message.ValuesForNETJson.Count; 
      for (int i = 0; i < count; i++) 
      { 
       string key = message.Arguments.ElementAt(i).Key; 
       Type type = message.TypesForNETJson.ElementAt(i).Value; 
       byte[] value = message.ValuesForNETJson[key]; 
       message.Arguments[key] = NETJsonFormatter.DeserializeWithType(type, value); 
      } 
      return message; 
     } 
     catch (Exception ex) 
     { 
      return null; 
     } 
    } 
} 

可以肯定我的解決方案將被重新設計的原因,而是不是最優的,遠從那。 向類中添加兩個Dictionary使其增長並比使用ProtoBuf序列化的同類更大,並使其變慢。