具有巨大IEnumerable的对象的JSON序列化非常慢

时间:2018-10-17 17:28:15

标签: c# .net json

我想将Result对象序列化为JSON,但是要花很多时间,例如整个过程只花1.5秒而没有序列化部分就需要1分钟以上。

我已经尝试过使用Json.NET和fastJSON,但是两者的速度相同。

IEnumerable<IEnumerable<int>> geometry中的

ResultFeature可能真的很大,因为它可以包含成千上万的整数。

为什么要花这么长时间?

using System;
using System.Collections.Generic;
using fastJSON;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.esriSystem;

namespace DesktopConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var watch = System.Diagnostics.Stopwatch.StartNew();
            Result result = new Result
            {
                fields = new List<string>
                {
                    "CD_MUNCP",
                    "NOM_MUNCP"
                },
                features = CreateResultFeatures().ToList()
            };
            string json = JSON.ToJSON(result);
            watch.Stop();
            Console.WriteLine(watch.ElapsedMilliseconds);
            Console.ReadLine();
        }

        public class Result
        {
            public List<string> fields { get; set; }
            public string geometryType { get; set; }
            public IEnumerable<ResultFeature> features { get; set; }
        }

        public class ResultFeature
        {
            public Dictionary<string, dynamic> attributes { get; set; }
            public IEnumerable<IEnumerable<int>> geometry { get; set; }
        }

        public static IEnumerable<ResultFeature> CreateResultFeatures()
        {
            IWorkspace gdbWorkspace = FileGdbWorkspaceFromPath(@"\\vnageop1\geod\Maxime\test.gdb");
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)gdbWorkspace;
            IFeatureClass featureClass = featureWorkspace.OpenFeatureClass(@"GEO09E04_MUNCP_GEN");
            IQueryFilter queryFilter = new QueryFilterClass();
            queryFilter.SubFields = "CD_MUNCP, NOM_MUNCP, SHAPE";

            int cd_muncp_idx = featureClass.FindField("CD_MUNCP");
            int nom_muncp_idx = featureClass.FindField("NOM_MUNCP");

            using (ComReleaser comReleaser = new ComReleaser())
            {
                IFeatureCursor cursor = featureClass.Search(queryFilter, false);
                comReleaser.ManageLifetime(cursor);
                IFeature feature = null;
                while ((feature = cursor.NextFeature()) != null)
                {
                    ResultFeature resultFeature = new ResultFeature
                    {
                        attributes = new Dictionary<string,dynamic>
                        {
                            { "CD_MUNCP", Convert.ToString(feature.Value[cd_muncp_idx]) },
                            { "NOM_MUNCP", Convert.ToString(feature.Value[nom_muncp_idx]) }
                        },
                        geometry = PolygonToDeltas(feature.Shape as IPolygon4).ToLiist()
                    };
                    yield return resultFeature;
                }
            }
        }

        public static IEnumerable<IEnumerable<int>> PolygonToDeltas(IPolygon4 polygon)
        {
            IGeometryBag exteriorRingGeometryBag = polygon.ExteriorRingBag;
            IGeometryCollection exteriorRingGeometryCollection = exteriorRingGeometryBag as IGeometryCollection;
            for (int i = 0; i < exteriorRingGeometryCollection.GeometryCount; i++)
            {
                IGeometry exteriorRingGeometry = exteriorRingGeometryCollection.get_Geometry(i);
                IPointCollection exteriorRingPointCollection = exteriorRingGeometry as IPointCollection;
                yield return CreateDeltas(exteriorRingPointCollection);

                IGeometryBag interiorRingGeometryBag = polygon.get_InteriorRingBag(exteriorRingGeometry as IRing);
                IGeometryCollection interiorRingGeometryCollection = interiorRingGeometryBag as IGeometryCollection;
                for (int k = 0; k < interiorRingGeometryCollection.GeometryCount; k++)
                {
                    IGeometry interiorRingGeometry = interiorRingGeometryCollection.get_Geometry(k);
                    IPointCollection interiorRingPointCollection = interiorRingGeometry as IPointCollection;
                    yield return CreateDeltas(interiorRingPointCollection);
                }
            }
        }

        private static IEnumerable<int> CreateDeltas(IPointCollection pointCollection)
        {
            int previous_x = (int)pointCollection.get_Point(0).X;
            int previous_y = (int)pointCollection.get_Point(0).Y;
            yield return previous_x;
            yield return previous_y;
            for (int i = 1; i < pointCollection.PointCount; i++)
            {
                int current_x = (int)pointCollection.get_Point(i).X;
                int current_y = (int)pointCollection.get_Point(i).Y;
                yield return previous_x - current_x;
                yield return previous_y - current_y;
                previous_x = current_x;
                previous_y = current_y;
            }
        }
    }
}

0 个答案:

没有答案