使用以复杂类型为键的对象引用和字典将复杂类型序列化/反序列化为Json



我正在尝试序列化/反序列化一个复杂类型。我希望保留对象引用,这意味着如果对象的实例在对象图中被多次引用,那么在反序列化过程中,我希望反序列化器只创建一次该实例并多次引用它(而不是多次创建该对象实例)。

我需要系统处理的第二件事是一个字典,其中键本身就是一个复杂的类型。

我能够通过DataContractSerializer序列化到XML来实现这两个功能。然而,我找不到任何Json序列化程序可以做到这一点。我试过Json.NET和ServiceStack,但没有成功。

请参阅下面的示例代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using Newtonsoft.Json;
namespace Serialization
{
    class Program
    {
        static void Main(string[] args)
        {
            var transportModel = CreateSampleModel();

            //Serialize with DataContractSerializer
            var serializer = new DataContractSerializer(typeof(TransportModel), null, int.MaxValue, false, true, null, null);
            string serializedObjectXml;
            using (var sw = new StringWriter())
            {
                using (var writer = new XmlTextWriter(sw))
                {
                    serializer.WriteObject(writer, transportModel);
                    writer.Flush();
                    serializedObjectXml = sw.ToString();
                }
            }
            //Deserialize with DataContractSerializer
            byte[] byteArray = Encoding.ASCII.GetBytes(serializedObjectXml);
            var stream = new MemoryStream(byteArray);
            var deserializedObjectXml = serializer.ReadObject(stream);

            //Serialize with Json.NET
            var serializedObjectJson=JsonConvert.SerializeObject(transportModel);
            //Deserialize with Json.NET - this fails because of the key in the dictionary being a complex type
            var deserializedObjectJson = JsonConvert.DeserializeObject(serializedObjectJson);
        }

        static TransportModel CreateSampleModel()
        {
            var transportModel = new TransportModel();
            // dests
            var fra = new Destination
            {
                Id = 0,
                Name = "FRA",
                Demand = 900
            };
            var det = new Destination
            {
                Id = 1,
                Name = "DET",
                Demand = 1200
            };

            var dests = new List<Destination> { fra, det};
            //origs
            var gary = new Origin
            {
                Id = 0,
                Name = "GARY",
                Supply = 1400,
                Cost = new Dictionary<Destination, int>{
                    {fra, 39},
                    {det, 14}
                }
            };

            var origs = new List<Origin> { gary};
            transportModel.Destinations = dests;
            transportModel.Origins = origs;
            return transportModel;
        }
    }
    [DataContract]
    class Destination
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public int Demand { get; set; }
    }
    [DataContract]
    class Origin
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public int Supply { get; set; }
        [DataMember]
        public Dictionary<Destination, int> Cost { get; set; }
    }
    [DataContract]
    class TransportModel
    {
        [DataMember]
        public List<Origin> Origins;
        [DataMember]
        public List<Destination> Destinations;
        public TransportModel()
        {
            Origins = new List<Origin>();
            Destinations = new List<Destination>();
        }
    }
}
Json.NET支持处理对象引用:保留对象引用

复杂类型字典键可以通过创建TypeConverter来处理,该TypeConverter将类型转换为字符串和从字符串转换类型。Json.NET将使用该字符串作为字典键。

使用.NET内置的BinaryFormatter,它保留引用。

尽管我个人不鼓励使用具有循环依赖关系的对象图Blob,但它是不可修改的、可内省的,并且处理版本控制更改的机会很小。

理想情况下,数据传输对象(即用于序列化的类型)应该是干净的、自我描述的,并以流行的、可版本控制的和宽容的格式进行序列化。

相关内容

  • 没有找到相关文章