NETJson,如何序列化自定义类型集合中的自定义类型
本文关键字:自定义 类型 集合 序列化 NETJson | 更新日期: 2023-09-27 18:04:53
我应该如何编写这部分代码来序列化所有后代自定义类型?
问题是关于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);
}
from wiki
字典—支持Value(Object)字典、illist、基本类型和枚举
我认为这是你的问题,只是尝试序列化一个对象字典,它会失败,但一个复杂类型的字典成功…
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
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序列化的类更大,并使其更慢。