Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用JSON.NET序列化POCO';s作为字符串列表,以减小大小?_C#_Serialization_Json.net - Fatal编程技术网

C# 如何使用JSON.NET序列化POCO';s作为字符串列表,以减小大小?

C# 如何使用JSON.NET序列化POCO';s作为字符串列表,以减小大小?,c#,serialization,json.net,C#,Serialization,Json.net,我有这样一个简单的POCO: public class Edit { ... } public class CharInsert : Edit { public int ParagraphIndex { get; set; } public int CharacterIndex { get; set; } public char Character { get; set; } } 在JSON中序列化如下(注意,由

我有这样一个简单的POCO:

    public class Edit { ... }

    public class CharInsert : Edit
    {
        public int ParagraphIndex { get; set; }
        public int CharacterIndex { get; set; }
        public char Character { get; set; }
    }
在JSON中序列化如下(注意,由于继承,我正在记录对象类型):

但这会占用大量空间来存储相当少的数据。我有很多,所以我需要更紧凑一些

我制作了一个定制的
JsonConverter
,因此它将改为如下序列化:

  "CharInsert|7|15|e"
当我坚持列出这些内容时,我得到:

[
  "CharInsert|7|12|Z",
  "CharInsert|7|13|w",
  "CharInsert|7|14|i",
  "CharInsert|7|15|e",
]
但是,当我尝试对该列表进行反序列化时,会出现以下错误:

'将值“CharInsert | 7 | 12 | Z”转换为类型“MyNamespace.Edit”时出错'


我想这是因为实际对象是Edit类型的子类,它不知道是哪一个,因为它不知道如何解析字符串。我如何实现它,以便它能够解析字符串,解析其中包含的类型名,然后创建所需的对象类型?

我已经解决了这个问题。问题是,如果序列化字符串中没有类型信息(
“CharInsert | 7 | 15 | e”
),反序列化程序不知道要调用哪个派生类

因此,我为基本的
Edit
类型制作了一个
JsonConverter
,它知道如何解析字符串并从该字符串创建和返回and对象:

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            //get the persisted value
            var s = reader.Value?.ToString();

            var fields = s.Split('|');
            var typeName = ...get the type name from the field

            var type = Type.GetType(typeName);

            //create an object from the remaining fields using the ctor(string value) that
            //each subclass must have
            return System.Activator.CreateInstance(type, new object[] { fields.Skip(1).ToJoinedString("|") });
        }

一种替代自定义转换器的方法,考虑使用<代码> [jsNealStices(PrimeNoTy= =)] < /C> >缩短JSON属性名称,这应该减少空间,而不必担心自定义转换器。

    public class CharInsert : Edit
    {
        [JsonProperty(PropertyName = "p")]
        public int ParagraphIndex { get; set; }
        [JsonProperty(PropertyName = "i")]
        public int CharacterIndex { get; set; }
        [JsonProperty(PropertyName = "c")]
        public char Character { get; set; }
    }

我会认真考虑改变这种做法,目前的实施非常脆弱和容易出错。假设对象中的字段在序列化和反序列化之间发生了变化?这不是因为序列化程序不知道类型,而是因为
“CharInsert | 7 | 15 | e”
不是有效的JSON对象。默认反序列化程序无法在非JSONI的
CharInsert
对象中填充属性。我不知道如果不使用JSON,为什么还要使用JSON.Net。@Dmitristoy:更改为什么?更改字段往往会打破传统序列化的平衡。@MindSwipe:数据类型是一个列表,我只想将T序列化为所示的字符串a,以节省大约90%的空间,同时仍然使用JSON作为文件格式。有点像“到Csv”的列表-ed然后将其包装在一个Json对象中,该对象的属性告诉您反序列化应该使用什么Csv配置?为什么不使用BSON或其他比Json更轻量级的格式?
    public class CharInsert : Edit
    {
        [JsonProperty(PropertyName = "p")]
        public int ParagraphIndex { get; set; }
        [JsonProperty(PropertyName = "i")]
        public int CharacterIndex { get; set; }
        [JsonProperty(PropertyName = "c")]
        public char Character { get; set; }
    }