2016-08-30 179 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序列化的同类更大,并使其变慢。