NETJson,如何在自定义类型集合中序列化自定义类型

时间:2016-08-30 09:29:51

标签: c# .net json serialization nested

我应该如何编写这部分代码来序列化所有后代自定义类型?

问题涉及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);
    }

2 个答案:

答案 0 :(得分:0)

来自wiki

  

词典        - 值(对象)支持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序列化的同类更大,并使其更慢。