如何序列化List< List< object>&gt ;? [英] How to serialize List<List<object>>?

查看:132
本文介绍了如何序列化List< List< object>&gt ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

框架是c#.net 4.6.2



我正在从XML代码生成自动XML类



当我自动生成时,它会自动转换为 Array [] []



但我想将其用作 List< List<>>



而且我确信我从Array到List的对话会引起一些序列化错误。我认为这与获取和设置功能有关。因此,我需要您的帮助来解决此问题



当我编辑>粘贴特殊>将XML粘贴为类时,这是自动生成的代码段

  ///<备注/> 
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute( code)]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
公共局部类OxFordDefinition_perGroup
{

私有字符串_GroupDescField;

私有字符串_GroupSenseField;

私有字符串_GroupGrammerField;

私有OxFordDefinition_perGroup_perMainExample_perSubExample [] [] _perMainExampleField;

///<备注/>
公共字符串_GroupDesc
{
get
{
返回this._GroupDescField;
}
set
{
this._GroupDescField = value;
}
}

///<备注/>
公共字符串_GroupSense
{
get
{
返回this._GroupSenseField;
}
set
{
this._GroupSenseField = value;
}
}

///<备注/>
公共字符串_GroupGrammer
{
get
{
返回this._GroupGrammerField;
}
set
{
this._GroupGrammerField = value;
}
}

///<备注/>
[System.Xml.Serialization.XmlArrayItemAttribute( _ perSubExample,typeof(OxFordDefinition_perGroup_perMainExample_perSubExample),IsNullable = false)]
public OxFordDefinition_perGroup_perMainExample_perSubExample [] [] _perMainExample
{
get $ $ b {
返回this._perMainExampleField;
}
set
{
this._perMainExampleField = value;
}
}
}

但是我不是数组,而是想要使用 List< List<>>



所以我在下面这样

  ///<备注/> 
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute( code)]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
公共局部类OxFordDefinition_perGroup
{

私有字符串_GroupDescField;

私有字符串_GroupSenseField;

私有字符串_GroupGrammerField;

private List< List< OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExampleField;

///<备注/>
公共字符串_GroupDesc
{
get
{
返回this._GroupDescField;
}
set
{
this._GroupDescField = value;
}
}

///<备注/>
公共字符串_GroupSense
{
get
{
返回this._GroupSenseField;
}
set
{
this._GroupSenseField = value;
}
}

///<备注/>
公共字符串_GroupGrammer
{
get
{
返回this._GroupGrammerField;
}
set
{
this._GroupGrammerField = value;
}
}

///<备注/>
[System.Xml.Serialization.XmlArrayItemAttribute( _ perSubExample,typeof(OxFordDefinition_perGroup_perMainExample_perSubExample),IsNullable = false)]
public List< List< OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExample
{
get
{
返回this._perMainExampleField;
}
set
{
this._perMainExampleField = value;
}
}
}

但这一次它提供了序列化当我尝试如下序列化时出现错误

 公共静态字符串SerializeXML< T>(此T toSerialize)
{
XmlSerializer xmlSerializer =新的XmlSerializer(typeof(T));
StringWriter textWriter = new StringWriter();
xmlSerializer.Serialize(textWriter,toSerialize);
返回textWriter.ToString();
}

这里是XML类的完整代码



解决方案

实际上,您的原始版本和修改后的 OxFordDefinition_perGroup 都无法成功序列化。问题是您的 XmlArrayItem.Type ,这是构造函数

  [System.Xml.Serialization.XmlArrayItemAttribute( _ perSubExample,typeof(OxFordDefinition_perGroup_perMainExample_perSubExample),IsNullable = false)] 
public OxFordDefinition_perGroup_perMainExample_perSubExample [] [] {get;组; }

根据文档



< blockquote>

使用Type属性为公共字段或公共读/写属性值指定重写的类型。



如果有字段或属性返回对象类型的数组,将 XmlArrayItemAttribute 的多个实例应用于字段或属性。对于每个实例,将Type属性设置为可以插入数组的对象类型。


typeof(OxFordDefinition_perGroup_perMainExample_perSubExample)表示最外层集合中的项目类型为 typeof(OxFordDefinition_perGroup_perMainExample_perSubExample)。但是,实际上,数组或列表中的项目的类型分别为 OxFordDefinition_perGroup_perMainExample_perSubExample [] List< OxFordDefinition_perGroup_perMainExample_perSubExample> 当然,不能将其分配给该类型。此 XmlSerializer 代码生成失败。



如果您从中完全删除类型设置[ XmlArrayItem] 属性,则您的两个版本都可以序列化为XML:

  [System.Xml .Serialization.XmlArrayItemAttribute( _ perSubExample,IsNullable = false)] 
public List< List< OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExample
{
get
{
返回this._perMainExampleField;
}
set
{
this._perMainExampleField = value;
}
}

示例小提琴



更新



您问,它添加了不应该存在的额外层。知道吗?



这是因为您使用的是嵌套列表或锯齿状数组。将其更改为简单列表或一维数组:

 私有列表< OxFordDefinition_perGroup_perGroupExample.perSubExample> _perMainExampleField; 

///<备注/>
[System.Xml.Serialization.XmlArrayItemAttribute( _ perSubExample,IsNullable = false)]
public List< OxFordDefinition_perGroup_perMainExample_perSubExample> _perMainExample
{
get
{
返回this._perMainExampleField;
}
set
{
this._perMainExampleField = value;
}
}

示例小提琴#2



然后我从 http://pastebin.com/raw/BJhRfFNf 并运行 xsd.exe 到生成一个架构,然后从XML中生成类,然后我能够重现您的问题-生成了错误的类。然后,我手动将锯齿状的数组更改为平面数组( List< T> 也可以正常工作),并且能够对XML进行序列化和反序列化,而不会引发异常:



示例提琴#3



不幸的是,似乎只有 first < / _ perMainExample> 节点已成功反序列化调整了类,因此在这一点上,此自动生成的代码似乎并不可行。



我不确定为什么 xsd.exe 在此处生成了错误的代码,您可能想问另一个问题或与Microsoft讨论问题。



最终更新



看起来好像 xsd .exe (因此将XML粘贴为类)遇到了包含嵌套重复元素的重复元素的问题:

 < _perMainExample> 
< _perSubExample>
< / _ perSubExample>

< _perSubExample>
< / _ perSubExample>
< / _ perMainExample>

< _perMainExample>
< _perSubExample>
< / _ perSubExample>

< _perSubExample>
< / _ perSubExample>
< / _ perMainExample>

我不确定是什么问题,但是在这一点上,我建议切换到其他代码生成工具,例如 https://xmltocsharp.azurewebsites.net/ ,它会生成以下类: / p>

  [XmlRoot(ElementName = _ Example)] 
公共类_Example {
[XmlElement(ElementName = _SenseNot)]
公共字符串_SenseNot {get;组; }
[XmlElement(ElementName = _ GrammaticNot)]
公共字符串_GrammaticNot {get;组; }
[XmlElement(ElementName = _ Desc)]
公共字符串_Desc {get;组; }
}

[XmlRoot(ElementName = _ perSubExample)]
公共类_perSubExample {
[XmlElement(ElementName = _ UpperTitle)]
公用字符串_UpperTitle {get;组; }
[XmlElement(ElementName = _ FormGroup)]
公共字符串_FormGroup {get;组; }
[XmlElement(ElementName = _ SenseNot)]
公共字符串_SenseNot {get;组; }
[XmlElement(ElementName = _ GrammaticNot)]
公共字符串_GrammaticNot {get;组; }
[XmlElement(ElementName = _ Desc)]
公共字符串_Desc {get;组; }
[XmlElement(ElementName = _ Example)]
public List< _Example> _Example {get;组; }
[XmlElement(ElementName = _ Synonyms)]
公共字符串_Synonyms {get;组; }
}

[XmlRoot(ElementName = _ perMainExample)]
公共类_perMainExample {
[XmlElement(ElementName = _ perSubExample)]
公共列表< _perSubExample> _perSubExample {get;组; }
}

[XmlRoot(ElementName = _ perGroup)]
公共类_perGroup {
[XmlElement(ElementName = _ GroupDesc)]
公用字符串_GroupDesc {get;组; }
[XmlElement(ElementName = _ GroupSense)]
公共字符串_GroupSense {get;组; }
[XmlElement(ElementName = _ GroupGrammer)]
公共字符串_GroupGrammer {get;组; }
[XmlElement(ElementName = _ perMainExample)]
public List< _perMainExample> _perMainExample {get;组; }
}

[XmlRoot(ElementName = OxFordDefinition)]
公共类OxFordDefinition {
[XmlElement(ElementName = sourceURL)]
公共字符串SourceURL {get;组; }
[XmlElement(ElementName = originDesc)]
公共字符串OriginDesc {get;组; }
[XmlElement(ElementName = _ perGroup)]
public List< _perGroup> _perGroup {get;组; }
}

请注意:


  1. 生成的代码要干净得多。


  2. 附加级别的类 _perMainExample 被添加以封装内部的 _perSubExample 列表。


样本小提琴#4 显示原始XML和重新序列化的XML是相同的通过调用 XNode.DeepEquals()


Framework is c# .net 4.6.2

I am generating automatic XML classes from XML codes

When I auto generate, it automatically converts as Array[][]

But i want to use it as List<List<>>

And i am sure that my conversation from Array to List causes some serialization error. I think it is about get and set functions. So i need your help to fix this issue

Here the auto generated code piece when i edit > paste special > paste XML as classes

    /// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OxFordDefinition_perGroup
{

    private string _GroupDescField;

    private string _GroupSenseField;

    private string _GroupGrammerField;

    private OxFordDefinition_perGroup_perMainExample_perSubExample[][] _perMainExampleField;

    /// <remarks/>
    public string _GroupDesc
    {
        get
        {
            return this._GroupDescField;
        }
        set
        {
            this._GroupDescField = value;
        }
    }

    /// <remarks/>
    public string _GroupSense
    {
        get
        {
            return this._GroupSenseField;
        }
        set
        {
            this._GroupSenseField = value;
        }
    }

    /// <remarks/>
    public string _GroupGrammer
    {
        get
        {
            return this._GroupGrammerField;
        }
        set
        {
            this._GroupGrammerField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", typeof(OxFordDefinition_perGroup_perMainExample_perSubExample), IsNullable = false)]
    public OxFordDefinition_perGroup_perMainExample_perSubExample[][] _perMainExample
    {
        get
        {
            return this._perMainExampleField;
        }
        set
        {
            this._perMainExampleField = value;
        }
    }
}

But instead of arrays, i want to use List<List<>>

So i make it like below

        /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class OxFordDefinition_perGroup
    {

        private string _GroupDescField;

        private string _GroupSenseField;

        private string _GroupGrammerField;

        private  List<List<OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExampleField;

        /// <remarks/>
        public string _GroupDesc
        {
            get
            {
                return this._GroupDescField;
            }
            set
            {
                this._GroupDescField = value;
            }
        }

        /// <remarks/>
        public string _GroupSense
        {
            get
            {
                return this._GroupSenseField;
            }
            set
            {
                this._GroupSenseField = value;
            }
        }

        /// <remarks/>
        public string _GroupGrammer
        {
            get
            {
                return this._GroupGrammerField;
            }
            set
            {
                this._GroupGrammerField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", typeof(OxFordDefinition_perGroup_perMainExample_perSubExample), IsNullable = false)]
        public List<List<OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExample
        {
            get
            {
                return this._perMainExampleField;
            }
            set
            {
                this._perMainExampleField = value;
            }
        }
    }

But this time it gives serialization error when i try to serialize like below

       public static string SerializeXML<T>(this T toSerialize)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        StringWriter textWriter = new StringWriter();
        xmlSerializer.Serialize(textWriter, toSerialize);
        return textWriter.ToString();
    }

Here the full code of the XML class

http://pastebin.com/y5B8ENM3

Here the error it gives

解决方案

Actually neither your original nor your modified OxFordDefinition_perGroup can be serialized successfully. The problem is your value for XmlArrayItem.Type, which is the second argument to the constructor:

[System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", typeof(OxFordDefinition_perGroup_perMainExample_perSubExample), IsNullable = false)]
public OxFordDefinition_perGroup_perMainExample_perSubExample[][] { get; set; }

According to the docs

Use the Type property to specify an overridden type for a public field or public read/write property value.

If a field or property returns an array of type Object, apply multiple instances of the XmlArrayItemAttribute to the field or property. For each instance, set the Type property to a type of object that can be inserted into the array.

The typeof(OxFordDefinition_perGroup_perMainExample_perSubExample) indicates that items in the outermost collection will be of type typeof(OxFordDefinition_perGroup_perMainExample_perSubExample). However, in fact the items in the array or list are of type OxFordDefinition_perGroup_perMainExample_perSubExample[] or List<OxFordDefinition_perGroup_perMainExample_perSubExample> respectively, which cannot, of course, be assigned to this type. This XmlSerializer code generation fails.

If you remove the type setting entirely from your [XmlArrayItem] attribute then both versions of your type will be serializable to XML:

[System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", IsNullable = false)]
public List<List<OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExample
{
    get
    {
        return this._perMainExampleField;
    }
    set
    {
        this._perMainExampleField = value;
    }
}

Sample fiddle.

Update

You asked, it adds extra layer which should not exists. any idea?

This is because you are using nested lists or jagged arrays. Change it to be a simple list or 1-d array:

private List<OxFordDefinition_perGroup_perMainExample_perSubExample> _perMainExampleField;

/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", IsNullable = false)]
public List<OxFordDefinition_perGroup_perMainExample_perSubExample> _perMainExample
{
    get
    {
        return this._perMainExampleField;
    }
    set
    {
        this._perMainExampleField = value;
    }
}

Sample fiddle #2.

I then downloaded the entire XML from http://pastebin.com/raw/BJhRfFNf and ran xsd.exe to generate a schema, and then classes, from the XML, and I was able to reproduce your problem - incorrect classes were generated. I then manually changed the jagged array to a flat array (a List<T> would work fine also) and was able to serialize and deserialize the XML without an exception getting thrown:

Sample fiddle #3.

Unfortunately, it appears that only the first </_perMainExample> node is successfully deserialized using these tweaked classes, so at this point this auto-generated code just doesn't seem viable.

I'm not sure why xsd.exe generated bad code here, you might want to ask another question or open an issue with Microsoft.

Final Update

It looks as though xsd.exe (and thus Paste XML as Classes) is having trouble with a repeating element that contains nested repeating elements:

<_perMainExample>
  <_perSubExample>
  </_perSubExample>

  <_perSubExample>
  </_perSubExample>
</_perMainExample>

<_perMainExample>
  <_perSubExample>
  </_perSubExample>

  <_perSubExample>
  </_perSubExample>
</_perMainExample>

I'm not sure what the problem is, but at this point I recommend switching to a different code-generation tool such as https://xmltocsharp.azurewebsites.net/, which generates the following classes:

[XmlRoot(ElementName="_Example")]
public class _Example {
    [XmlElement(ElementName="_SenseNot")]
    public string _SenseNot { get; set; }
    [XmlElement(ElementName="_GrammaticNot")]
    public string _GrammaticNot { get; set; }
    [XmlElement(ElementName="_Desc")]
    public string _Desc { get; set; }
}

[XmlRoot(ElementName="_perSubExample")]
public class _perSubExample {
    [XmlElement(ElementName="_UpperTitle")]
    public string _UpperTitle { get; set; }
    [XmlElement(ElementName="_FormGroup")]
    public string _FormGroup { get; set; }
    [XmlElement(ElementName="_SenseNot")]
    public string _SenseNot { get; set; }
    [XmlElement(ElementName="_GrammaticNot")]
    public string _GrammaticNot { get; set; }
    [XmlElement(ElementName="_Desc")]
    public string _Desc { get; set; }
    [XmlElement(ElementName="_Example")]
    public List<_Example> _Example { get; set; }
    [XmlElement(ElementName="_Synonyms")]
    public string _Synonyms { get; set; }
}

[XmlRoot(ElementName="_perMainExample")]
public class _perMainExample {
    [XmlElement(ElementName="_perSubExample")]
    public List<_perSubExample> _perSubExample { get; set; }
}

[XmlRoot(ElementName="_perGroup")]
public class _perGroup {
    [XmlElement(ElementName="_GroupDesc")]
    public string _GroupDesc { get; set; }
    [XmlElement(ElementName="_GroupSense")]
    public string _GroupSense { get; set; }
    [XmlElement(ElementName="_GroupGrammer")]
    public string _GroupGrammer { get; set; }
    [XmlElement(ElementName="_perMainExample")]
    public List<_perMainExample> _perMainExample { get; set; }
}

[XmlRoot(ElementName="OxFordDefinition")]
public class OxFordDefinition {
    [XmlElement(ElementName="sourceURL")]
    public string SourceURL { get; set; }
    [XmlElement(ElementName="originDesc")]
    public string OriginDesc { get; set; }
    [XmlElement(ElementName="_perGroup")]
    public List<_perGroup> _perGroup { get; set; }
}

Notice that:

  1. The code generated is much, much cleaner.

  2. An extra level of class _perMainExample is added to encapsulate the inner _perSubExample list.

Sample fiddle #4 which shows that the original and re-serialized XML are identical by calling XNode.DeepEquals().

这篇关于如何序列化List&lt; List&lt; object&gt;&gt ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆