简体   繁体   中英

How do I not allow a property to be null or empty when deserializing XML?

I know Json.net has an attribute [JsonRequired]; are there any XML methods that can do the same thing?.

I don't think there is, so I have made my own way of doing so, but I have stopped at how to handle List and T in reflection.

It's a great help if someone will tell me, thanks.

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
{
}

I don't 100% know what you're trying to accomplish with what you're doing right now, and I also don't know which values you don't want to be null, but I do see that there is a much easier way of deserialzing XML into objects (see here for some reference):

[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; }
}

Once you have that, you can deserialize the xml wherever you want in the same file with:

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);

Null Checking

Using XML

Basically, you just add IsNullable = false inside the parenthesis of a [XmlArrayItem], for example, to make sure a specific value will not return null (It will skip over it). NOTE: I have only tested this on [XmlArrayItem] , I do not know for sure if it will work on other Xml tags...

Using C#

If you really wanted to use C# and throw and exception if it's null (which sort of ruins the point of using [XmlElement] in the first place), you can do something like this instead (see 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();
}

Using JSON

If you really want to use something like [JsonRequired], then why not just use it! You can convert the XML data to JSON data using Json.Net (see 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);

Now, you have your xml data in json format in string json , and you can do whatever you want to it, including setting up a map like I did with the xml and adding [JsonRequired]

someone told me,here is the answer.

 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));
        }
    }

Add a constructor

public TestXML()
{
   Sec = "";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM