我应该如何编写这部分代码来序列化所有后代自定义类型?
问题涉及NETJson(https://github.com/rpgmaker/NetJSON)。
在用于测试它的代码下面。
NETJson Serializer实现:
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上的测试,通过。 为确保数据一致,我在NUGet上使用DeepEqual(https://github.com/jamesfoster/DeepEqual - '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 :(得分:0)
词典 - 值(对象)支持Dictionary,IList,Primitive Types和Enums
我认为这是你的问题,只是尝试序列化一个对象dicitionnary,它会失败,但是一个complexType dictionnary会成功...
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
答案 1 :(得分:0)
NETJson没有正确地序列化Dictionary cause对象它是基类型但是它可以序列化很多基元(包括字节数组)所以我找到了一个解决方案(好吧,现在解决方法导致我的眼睛流血看着代码 - 但它很有效。)
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序列化的同类更大,并使其更慢。