Serialize nullable type to optional non-nillable element

前端 未结 2 1674
时光说笑
时光说笑 2021-01-18 22:35

I have an xsd schema with an optional element (minOccurs=0, maxOccurs=1) of type int. The element is NOT defined as nillable. In the d

相关标签:
2条回答
  • 2021-01-18 22:57

    I am not sure about XxxSpecified, but you can use the ShouldSerializeXxx methods. These happily work whether the property type is nullable or not. The following should do the job:

    public int? Property { get ; set ; }
    
    // this member is used for XML serialization
    public bool ShouldSerializeProperty () { return Property.HasValue ; }
    

    As for the generation of code from XSD schema, if you're using Microsoft's xsd.exe tool the best bet seems to be to post-process the generated assembly with e.g. Mono.Cecil to modify the types of the properties of interest and to insert any extra serialization-related members like ShouldSerializeXxx. Adding an XSLT pre-processing step to run xsd.exe on a 'fixed' schema with nillable element declarations achieves the first goal, but not the second. xsd.exe is not flexible enough to do what you want. You might also try adding this functionality to xsd2code, since it's open-source.

    0 讨论(0)
  • 2021-01-18 22:58

    I also encountered with this problem some time ago. I solved it by introducing additional property that handles serialization logic.

    1. Firstly you mark your original property with [XmlIgnore] attribute to exlude it from serialization/deserialization.

      // Mark your original property from serialization/deserialization logic
      [XmlIgnore]
      public int? OriginalProperty { get; set; }
      
    2. Then add the additional property and mark it with [XmlElement("YourElementName")] attribute to handle serialization logic.

      // Move serialization logic to additional string property
      [XmlElement("OriginalPropertyXmlElement")]
      public string OriginalPropertyAsString
      {
          get
          {
              //...
          }
          set
          {
              //...
          }
      }
      
    3. On deserialization it will:

      set
      {
          // Check the field existence in xml
          if (string.IsNullOrEmpty(value))
          {
              // Set the original property to null
              this.OriginalProperty = default(int?);
          }
          else
          {
              // Get value from xml field
              this.OriginalProperty = int.Parse(value);
          }
      }
      
    4. On serialization:

      get
      {
          if (this.OriginalProperty.HasValue)
          {
              // Serialize it
              return this.OriginalProperty.ToString();
          }
          else
          {
              // Don't serialize it
              return null;
          }
      }
      
    5. The example could look like:

      [XmlRoot("scene")]
      public class Scene
      {
          [XmlIgnore]
          public int? ParentId { get; set; }
      
          [XmlElement("parent_id")]
          public string ParentIdAsString
          {
              get
              {
                  return this.ParentId.HasValue ? this.ParentId.ToString() : null;
              }
      
              set
              {
                  this.ParentId = !string.IsNullOrEmpty(value) ? int.Parse(value) : default(int?);
              }
          }
      }
      

    It's pretty simple and you don't have to write your own serializer nor hacking xsd nor other stuff.

    0 讨论(0)
提交回复
热议问题