在反序列化XML时,如何不允许属性为null或为空?

时间:2016-05-19 01:42:14

标签: c# xml serialization

我知道Json.net有一个属性[JsonRequired];是否有任何XML方法可以做同样的事情?。

我认为没有,所以我已经按照自己的方式这样做,但我已经停止了如何处理反射中的List和T.

如果有人告诉我,这是一个很好的帮助,谢谢。

class Program
{
    static void Main(string[] args)
    {
        string strin = "<TestXML><Fir>f</Fir><TestXML1><TestXML3><For>444</For></TestXML3></TestXML1></TestXML>";
        TestXML ttt1 = XmlToModel<TestXML>(strin);
        Console.ReadKey();
    }
    public static T XmlToModel<T>(string xml)
    {
        StringReader xmlReader = new StringReader(xml);
        XmlSerializer xmlSer = new XmlSerializer(typeof(T));
        T t = (T)xmlSer.Deserialize(xmlReader);
        Type typeT = typeof(T);
        IfIsClass<T>(typeT, t);
        return t;
    }
    private static void IfIsClass<T>(Type typeT, T t)
    {
        foreach (PropertyInfo p in typeT.GetProperties())
        {
            //here I don't konw how to handle List<T> and T

            //if(is List<T> or T)
            //  IfisClass<T>(typeT,t);
            IfIsNull<T>(p, t);
        }
    }
    private static void IfIsNull<T>(PropertyInfo p, T t)
    {
        var at = p.GetCustomAttribute(typeof(NotNullAttribute));
        var pvalue = p.GetValue(t);
        if (at != null && string.IsNullOrEmpty(pvalue == null ? "" : pvalue.ToString()))
        {
            throw new Exception(string.Format("Field {0} not allow null or empty", p.Name));
        }
    }
}
public class TestXML
{
    public string Fir { get; set; }
    [NotNull]
    public string Sec { get; set; }
    [XmlElement("")]
    public List<TestXML2> TestXML1 { get; set; }
}
public class TestXML2
{
    public string Thir { get; set; }
    public TestXML3 TestXML3 { get; set; }
}
public class TestXML3
{
    [NotNull]
    public string For { get; set; }
}
public class NotNullAttribute : Attribute
{
}

3 个答案:

答案 0 :(得分:1)

我不会100%知道你现在正在做什么,而且我也不知道你不想要的是哪些价值观为null,但我确实看到有一种更简单的方法将XML反序列化为对象(参见here以供参考):

[XmlRoot("TestXML")]
public class TestXML
{
    [XmlElement("Fir")]
    public string Fir { get; set; }

    [XmlArray("TestXML1")]
    [XmlArrayItem("TestXML3", IsNullable = false)]
    public TestXML3[] testxml3 { get; set; }
}

public class TestXML3
{
    [XmlElement("For")]
    public int For { get; set; }
}

public class Order
{
    [XmlElement("number")]
    public string Number { get; set; }
}

完成后,您可以使用以下命令在同一文件中的任何位置反序列化xml:

string xml = @"<TestXML><Fir>f</Fir><TestXML1><TestXML3><For>444</For></TestXML3></TestXML1></TestXML>";
StringReader reader = new StringReader(xml);
XmlSerializer ser = new XmlSerializer(typeof(TestXML));
var data = (TestXML)ser.Deserialize(reader);

空检查

使用XML

基本上,您只需在[XmlArrayItem]的括号内添加IsNullable = false,以确保特定值不会返回null(它将跳过它)。 注意: 我只在[XmlArrayItem]上对此进行了测试,我不确定它是否适用于其他Xml标记......

使用C#

如果你真的想要使用C#并抛出异常,如果它是null(这首先破坏了使用[XmlElement]的意义),你可以做这样的事情(见here):

... //same code as before
var data = (TestXML)ser.Deserialize(reader);
//haven't tested this
foreach(obj dataobj in data){
    if(dataobj == null) throw new NullReferenceException();
}

使用JSON

如果你真的想使用像[JsonRequired]这样的东西,那么为什么不用它呢!您可以使用Json.Net将XML数据转换为JSON数据(请参阅here):

string xml = @"<TestXML><Fir>f</Fir><TestXML1><TestXML3><For>444</For></TestXML3></TestXML1></TestXML>";
XmlDocument Test = new XMLDocument();
Test.loadXml(xml);
string json = JsonConvert.SerializeXmlNode(Test);

现在,您可以在string json中以json格式获取xml数据,并且可以执行任何您想要的操作,包括像使用xml一样设置地图并添加[JsonRequired]

答案 1 :(得分:0)

有人告诉我,这是答案。

 public static T XmlToModel<T>(string xml)
    {
        StringReader xmlReader = new StringReader(xml);
        XmlSerializer xmlSer = new XmlSerializer(typeof(T));
        T t = (T)xmlSer.Deserialize(xmlReader);
        Type typeT = typeof(T);
        IfIsClass(t);
        return t;
    }
    private static void IfIsClass(object t)
    {
         var typeT = t.GetType();
        foreach (PropertyInfo p in typeT.GetProperties())
        {
            if (typeof(System.Collections.ICollection).IsAssignableFrom(p.PropertyType))
            {
                var vValue = p.GetValue(t, null) as System.Collections.ICollection;
                foreach(var item in vValue )
                {
                    IfIsClass(item);
                }
            }
            else
            {
                IfIsNull(p, p.GetValue(t, null));
            }
        }
    }
    private static void IfIsNull(PropertyInfo p, object pvalue)
    {
        var at = p.GetCustomAttribute(typeof(NotNullAttribute));
        if (at != null && string.IsNullOrEmpty(pvalue == null ? "" : pvalue.ToString()))
        {
            throw new Exception(string.Format("field[{0}]not allow null or empty", p.Name));
        }
    }

答案 2 :(得分:-4)

添加构造函数

public TestXML()
{
   Sec = "";
}