XmlSerializer , base64 encode a String member

北城余情 提交于 2019-12-19 07:52:46

问题


Consider a simple case

public class Test {
  public String myString;
}

Is there any way I can tell XmlSerializer to base64 encode myString when serializing it ?


回答1:


You can simply set it to be a byte[] property and it will Base64 encode it automatically:

public class Test {
  public byte[] MyProperty {get;set;}

  public void SetMyProperty(string text)
  {
      MyProperty = System.Text.Encoding.Unicode.GetBytes(text);
  }
}

Test test = new Test();
test. SetMyProperty("123456789123456789");

Output:

<MyProperty>MQAyADMANAA1ADYANwA4ADkAMQAyADMANAA1ADYANwA4ADkA</MyProperty>

(Try decoding that here)

Unfortunately there is no way (that I know of) to make MyProperty private and still be serialized in System.Xml.Serialization.




回答2:


Base64 converts binary data into a string. If you want to base64 encode the data in a string, you'd need to encode it in byte array first, e.g. using Encoding.UTF.GetBytes(myString).

This raises the question of why exactly you'd want to do this in the first place. If you need to use base 64, are you sure that you've really got text data to start with?




回答3:


Following Jon Grant useful suggestion I've implemented a Base64String type that encapsulate the required Base64 Encoding.

public class Base64String: IXmlSerializable
{
    private string value;

    public Base64String() { } 

    public Base64String(string value)
    {
        this.value = value;
    }

    public string Value
    {
        get { return value; }
        set { this.value = value; }
    }

    public static implicit operator string(Base64String x)
    {
        return x.ToString();
    }

    public static implicit operator Base64String(string x)
    {
        return new Base64String(x);
    }

    public override string ToString()
    {
        return value;
    }

    #region IXmlSerializable Members

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        MemoryStream ms = null;
        byte[] buffer = new byte[256];
        int bytesRead;

        while ((bytesRead = reader.ReadElementContentAsBase64(buffer, 0, buffer.Length)) > 0)
        {
            if (ms == null) 
                ms = new MemoryStream(bytesRead);

            ms.Write(buffer, 0, bytesRead);
        }

        if (ms != null)
            value = System.Text.UnicodeEncoding.Unicode.GetString(ms.ToArray());
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        if (!string.IsNullOrEmpty(value))
        {
            byte[] rawData = Encoding.Unicode.GetBytes(value);
            writer.WriteBase64(rawData, 0, rawData.Length); 
        }
    }

    static public string EncodeTo64(string toEncode)
    {
        byte[] toEncodeAsBytes
              = System.Text.UnicodeEncoding.Unicode.GetBytes(toEncode);
        string returnValue
              = System.Convert.ToBase64String(toEncodeAsBytes);
        return returnValue;
    }

    static public string DecodeFrom64(string encodedData)
    {
        byte[] encodedDataAsBytes
            = System.Convert.FromBase64String(encodedData);
        string returnValue =
           System.Text.UnicodeEncoding.Unicode.GetString(encodedDataAsBytes);
        return returnValue;
    }

    #endregion
}

And you can use the type like this:

static void Main(string[] args)
{
    Foo foo = new Foo();
    foo.Field1 = "Pluto";
    foo.Field2 = "Pippo";
    foo.Field3 = "Topolino";
    foo.Field4 = "Paperino";

    XmlSerializer ser = new XmlSerializer(typeof(Foo));
    ser.Serialize(Console.Out, foo);
    Console.ReadLine();
}

[XmlRoot("Sample")]
public class Foo
{   
    public Foo() { }

    [XmlElement("Alfa_64")]
    public Base64String Field1;

    [XmlElement("Beta")]
    public string Field2;

    [XmlElement("Gamma_64")]
    public Base64String Field3;

    [XmlElement("Delta_64")]
    public Base64String Field4;
}



回答4:


You store the string as a Base64 value, and then have a property which decodes it in the get clause.




回答5:


The only supported way to change the output from the XmlSerializer class (without ugly hacks like having special hidden properties etc) is to implement the IXmlSerializable interface.

You could save yourself having to write serialization code for the whole class by defining a Base64String class that implements IXmlSerializable and just writes out the encoded string. Define an operator to make it implicitly castable to a string and it should work pretty much like a normal string does.



来源:https://stackoverflow.com/questions/1405051/xmlserializer-base64-encode-a-string-member

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!