Deserializing a String Array

I have an xml file that contains a serialized object. I am trying to deserialize individual properties of the object from the file. For example:

<?

xml version="1.0"?>
<
MySerializedObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Foos
>
<
Foo
>
<
Prop1>xxx</Prop1
>
<
Prop2>xxx</Prop2
>
<
Prop3>xxx</Prop3
>
</Foo
>
<Foo
>
<
Prop1>xxx</Prop1
>
<
Prop2>xxx</Prop2
>
<
Prop3>xxx</Prop3
>
</Foo>
</Foos>
<Bars
>
<
Bar
>xxx</Bar>
<Bar
>xxx</Bar>
<Bar>xxx</Bar>
<Bar>xxx</Bar>
</Bars>
</MySerializedObject>

The preceding listing shows a serialized object that has and array of Foo objects and an array of strings. However, the string[] property has the following attributes:

[XmlArray(

"Bars"), XmlArrayItem("Bar", typeof(string))]

Deserializing this using an XmlSerializer works. Furthermore, I can deserialize the Foo array by itself by advancing an XmlReader to the Foo array and using an XmlSerializer with the reader and the following XmlAttributeOverrides:

XmlAttributes

attrs = new XmlAttributes();
attrs.XmlRoot = new XmlRootAttribute("Foos");
attrs.XmlType =
new XmlTypeAttribute("Foo");

However, this same method does not work with the string array. How can I get an array of strings from the "Bars" node of the xml file? Deserializing a "MySerializedObject" works but I only need a single array at a time, no need to read through the whole thing.

Adam Christopher

I'll be a little clearer. Consider the following:

[

XmlRoot("Foo")]
class
Foo
{
    int _id = 0;

    [XmlElement("ID")]
    public int
ID
    {
        get { return
_id; }
        set { _id = value
; }
    }
}

[

XmlRoot("MySerializedObject")]
class
MySerializedObject
{
 
    private
ArrayList
_fooArray = new ArrayList
();
    private ArrayList _barArray = new ArrayList();

    public

MySerializedObject()
    {
        _fooArray.Add(
new Foo
());
        _fooArray.Add(
new Foo());

        _barArray.Add("xxx");
        _barArray.Add(
"xxx"
);
        _barArray.Add(
"xxx"
);
        _barArray.Add(
"xxx"
);
    }

    [XmlArray("Foos"), XmlArrayItem("Foo", typeof(Foo))]
    public Foo
[] Foos
    {
        get { return (Foo[])_fooArray.ToArray(typeof(Foo));
 }
        set { _fooArray = new ArrayList(value
); }
    }

    [

XmlArray("Bars"), XmlArrayItem("Bar", typeof(string))]
    public string
[] Bars
    {
        get { return (string[])_barArray.ToArray(typeof(string));
 }
       
set { _barArray = new ArrayList(value
); }
    }
}

When serialized the following XML is produced:

<?xml version="1.0"?>
<
MySerializedObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">   
    <Foos
>
        <
Foo
>
            <
ID>0</ID>

        </Foo>
        <Foo
>
            <ID>0</ID>

        </Foo>
    </Foos>
    <Bars
>
        <
Bar
>xxx</Bar>
        <Bar
>xxx</Bar>
        <Bar>xxx</Bar>
        <Bar>xxx</Bar>
    </Bars>
</MySerializedObject>

When deserialized as a "MySerializedObject" object, everything works as expected. The problem arrises when trying to update the individual properties of the "MySerializedObject". Suppose I add the following method to the "MySerializedObject" class:

public

object UpdateProperty(string xmlArrayName, string xmlArrayItemName, Type xmlArrayItemType)
{
    XmlArrayAttribute arrAttr = new XmlArrayAttribute
(xmlArrayName);
    XmlArrayItemAttribute itemAttr = new XmlArrayItemAttribute(xmlArrayItemName, xmlArrayItemType);

    XmlAttributes attrs = new XmlAttributes();
    attrs.XmlArray = arrAttr;
    attrs.XmlArrayItems.Add(itemAttr);

 

    Stream xmlFileStream = new FileStream("MySerializedObject.xml", FileMode.Open);
    XmlTextReader xmlTextReader = new XmlTextReader(xmlFileStream);

    XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
    attrOverrides.Add(xmlArrayItemType.MakeArrayType(), attrs);

 

    XmlSerializer xmlSerializer = new XmlSerializer(xmlArrayItemType.MakeArrayType(), attrOverrides);

 

    if (xmlTextReader.ReadToFollowing(xmlArrayName))
    {
        XmlReader
xmlReader = xmlTextReader.ReadSubtree();
        object
objToReturn = xmlSerializer.Deserialize(xmlReader);
        xmlReader.Close();
        xmlTextReader.Close();
        xmlFileStream.Close();
        return
objToReturn;
    }
    return null
;
}

And now assign the value of this method to either property as follows:

MySerializedObject

myObj = new MySerializedObject();
myObj.Foos = (Foo[])GetPropertyFromXml(
"Foos", "Foo", typeof(Foo
));
myObj.Bars = (string[])GetPropertyFromXml(
"Bars", "Bar", typeof(string));

The instantiation of the "XmlSerializer" throws and "InvalidOperationException" with the following message: {"There was an error reflecting type 'Foo[]'."}
And the following inner exception, also and "InvalidOperationException", with the following message: {"XmlRoot and XmlType attributes may not be specified for the type Foo[]."}

Now lets suppose I add the following method to the "MySerializedObject" class:

public

object GetFoosFromXml()
{
    XmlRootAttribute rootAttr = new XmlRootAttribute("Foos"
);

 

    XmlAttributes attrs = new XmlAttributes();
    attrs.XmlRoot = rootAttr;

 

    Stream xmlFileStream = new FileStream("MySerializedObject.xml", FileMode.Open);
    XmlTextReader xmlTextReader = new XmlTextReader
(xmlFileStream);

 

    XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
    attrOverrides.Add(
typeof(Foo
[]), attrs);

 

    XmlSerializer xmlSerializer = new XmlSerializer(typeof(Foo[]), attrOverrides);

 

    if (xmlTextReader.ReadToFollowing(rootAttr.ElementName))
    {
        XmlReader
xmlReader = xmlTextReader.ReadSubtree();
        object
objToReturn = xmlSerializer.Deserialize(xmlReader);
        xmlReader.Close();
        xmlTextReader.Close();
        xmlFileStream.Close();
        return
objToReturn;
    }
    return null
;
}

And now assign the value of this method to the Foos property as follows:

MySerializedObject

myObj = new MySerializedObject();
myObj.Foos = (
Foo[])GetFoosFromXml();

This works perfectly. Can someone please tell me why I can serialize those arrays with XmlArray attributes but I cannot deserialize them unless they are deserialized as a property of a "MySerializedObject"?

Adam Christopher

I figured out what was causing the problem, but I have once again been brought back to the original problem of not being able to deserialize a string array. The problem with the above code is the only the array types were being overriden and not the underlying types. The following shows the changes to the UpdateProperty method (method is now called GetPropertyFromXml; changes are highlighted in red):

public

object GetPropertyFromXml(string xmlArrayName, string xmlArrayItemName, Type xmlArrayItemType)
{
XmlAttributes arrayAttrs = new XmlAttributes
();
XmlAttributes itemAttrs = new XmlAttributes
();
XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();

arrayAttrs.XmlRoot = new XmlRootAttribute(xmlArrayName);
itemAttrs.XmlType =
new XmlTypeAttribute(xmlArrayItemName);

attrOverrides.Add(xmlArrayItemType.MakeArrayType(), arrayAttrs);
attrOverrides.Add(xmlArrayItemType, itemAttrs);

Stream xmlFileStream = new FileStream("out.xml", FileMode.Open);
XmlTextReader xmlTextReader = new XmlTextReader
(xmlFileStream);
XmlSerializer xmlSerializer = new XmlSerializer
(xmlArrayItemType.MakeArrayType(), attrOverrides);
if
(xmlTextReader.ReadToFollowing(arrayAttrs.XmlRoot.ElementName))
{
XmlReader
xmlReader = xmlTextReader.ReadSubtree();
object
objToReturn = xmlSerializer.Deserialize(xmlReader);
xmlReader.Close();
xmlTextReader.Close();
xmlFileStream.Close();
return
objToReturn;
}
return null
;
}

By overriding the underlying type in the array ("xmlArrayItemType" above), the problem was solved. However, the string array still cannot be deserialized. When the XmlSerializer is instantiated, an InvalidOperationException is thrown just like the previous post indicated, however, the innerexception message is now: {"XML attributes may not be specified for the type System.String."}. Is there any way to overcome this without creating wrapper classes for string array properties?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值