如何将集合序列化为字母数字字符串?

时间:2021-05-25 19:20:11

I need to express a collection of about 10-15 short strings (and maybe some ints) as a fairly compact alphanumeric string - one which I can send as a parameter in a get request.

我需要将一个大约10-15个短字符串(可能还有一些整数)的集合表示为一个相当紧凑的字母数字字符串 - 我可以在get请求中将其作为参数发送。

Basically, I'm thinking that my collection will be a hashtable, and I'd like to serialize it so it looks sort of like a viewstate string (only hopefully not so long!).

基本上,我认为我的集合将是一个哈希表,我想序列化它,所以它看起来有点像一个viewstate字符串(只希望不那么长!)。

eg. testpage.aspx?code=rO0ABXNyAAlTb21lQ2xhc3PSHbLk6OgfswIAA0kAAWl

and then testpage.aspx can deserialize this back to the original collection.

然后testpage.aspx可以将其反序列化回原始集合。

Is this possible?

这可能吗?

5 个解决方案

#1


One option here is to pick a delimiter, for example ¤; join the strings, encode them (perhaps UTF8), and pack the bytes as base-64...

这里的一个选择是选择一个分隔符,例如¤;加入字符串,对它们进行编码(可能是UTF8),并将字节打包为base-64 ...

    string[] data = {"abc","123", "def"};
    string s = string.Join("¤", data);
    byte[] raw = Encoding.UTF8.GetBytes(s);
    string alphaNumeric = Convert.ToBase64String(raw); // send this

(you may need to handle the few non-alphanumeric characters that base-64 uses).

(您可能需要处理base-64使用的少数非字母数字字符)。

And to reverse it:

并扭转它:

    raw = Convert.FromBase64String(alphaNumeric);
    s = Encoding.UTF8.GetString(raw);
    data = s.Split('¤');

If you want to send key/value pairs... well, the obvious choice would be query-string parameters themselves, since they are designed for this. But if you need it as a byte-stream:

如果你想发送键/值对......那么显而易见的选择就是查询字符串参数本身,因为它们是为此而设计的。但是如果你需要它作为字节流:

    var data = new DbConnectionStringBuilder();
    data["foo"] = "abc";
    data["bar"] = "123 + ;la";
    string s = data.ConnectionString;

    byte[] raw = Encoding.UTF8.GetBytes(s);
    string alphaNumeric = Convert.ToBase64String(raw); // send this

    raw = Convert.FromBase64String(alphaNumeric);
    s = Encoding.UTF8.GetString(raw);
    data.ConnectionString = s;
    foreach (string key in data.Keys)
    {
        Console.WriteLine(key + "=" + data[key]);
    }

#2


Why don't you just serialize the data using protobuf-net and pass it through the Session? Or, if it has to be a string, just use XmlSerializer?

为什么不用protobuf-net序列化数据并将其传递给Session?或者,如果它必须是一个字符串,只需使用XmlSerializer?

Personally, passing serialized data through the URL seems really bad to me!

就个人而言,通过URL传递序列化数据对我来说真的很糟糕!

#3


you can serialize your dictionary/hashtable to JSON, and then change it to base64 (just to make it a tad less visible and resolve possible usage of URL characters etc). or you can just URLEncode it.

你可以将你的字典/散列表序列化为JSON,然后将其更改为base64(只是为了让它变得不那么明显并解决URL字符的可能用法等)。或者你可以直接URLEncode它。

#4


You can use standard .Net serialization and serialize your object to a MemoryStream. You can then read out the contents of the MemoryStream as a byte array and use Convert.ToBase64String on the array to get a string representation of it.

您可以使用标准.Net序列化并将对象序列化为MemoryStream。然后,您可以将MemoryStream的内容作为字节数组读出,并使用数组上的Convert.ToBase64String来获取它的字符串表示形式。

To deserialize it you can do the opposite.

要反序列化,你可以做相反的事情。

If you are worried that the serialized object is too large, you can wrap the MemoryStream in a System.IO.Compression.DeflateStream to compress it.

如果您担心序列化对象太大,可以将MemoryStream包装在System.IO.Compression.DeflateStream中以压缩它。

#5


Thank you all, putting it together I wrote a test console app. I was a bit disappointed that the resulting string was so long.

谢谢大家,把它放在一起我写了一个测试控制台应用程序。结果字符串很长,我有点失望。

My example implements a DeflateStream, which for my datasize probably introduces more overhead than it saves with compression. But even without the compression it was still pretty big.

我的示例实现了一个DeflateStream,对于我的datasize可能会引入比压缩保存更多的开销。但即使没有压缩,它仍然很大。

What I was hoping to achieve was to make something slightly more compact (obfuscation for the user was a plus, but not critical) - I suspect that it'd actually be better for me to use a plain old parameterized string. Maybe JSON might be ok, but I'm using ASP.net 2.0, and I don't think that I get a readybaked json serializer there.

我希望实现的是使某些东西稍微更紧凑(对用户进行混淆是一个加分,但并不重要) - 我怀疑使用普通的旧参数化字符串实际上更好。也许JSON可能没关系,但我使用的是ASP.net 2.0,我认为我没有得到一个现成的json序列化器。

Nonetheless, I learnt something new and interesting, so thanks for that!

尽管如此,我学到了一些新的有趣的东西,谢谢!

    static void Main(string[] args)
    {
        Hashtable ht1 = new Hashtable(1);
        ht1.Add("name", "bob");
        Console.WriteLine(ToCompactString(ht1));

        Console.WriteLine();

        string str = "name:bob";
        Console.WriteLine(ToCompactString(str));
        Console.ReadLine();
    }

    private static string ToCompactString(object obj)
    {
        var ms = new MemoryStream();
        var ds = new DeflateStream(ms, CompressionMode.Compress);
        var bf = new BinaryFormatter();

        bf.Serialize(ds, obj);
        byte[] bytes = ms.ToArray();
        ds.Close();
        ms.Close();
        string result = Convert.ToBase64String(bytes);
        return result;
    }

#1


One option here is to pick a delimiter, for example ¤; join the strings, encode them (perhaps UTF8), and pack the bytes as base-64...

这里的一个选择是选择一个分隔符,例如¤;加入字符串,对它们进行编码(可能是UTF8),并将字节打包为base-64 ...

    string[] data = {"abc","123", "def"};
    string s = string.Join("¤", data);
    byte[] raw = Encoding.UTF8.GetBytes(s);
    string alphaNumeric = Convert.ToBase64String(raw); // send this

(you may need to handle the few non-alphanumeric characters that base-64 uses).

(您可能需要处理base-64使用的少数非字母数字字符)。

And to reverse it:

并扭转它:

    raw = Convert.FromBase64String(alphaNumeric);
    s = Encoding.UTF8.GetString(raw);
    data = s.Split('¤');

If you want to send key/value pairs... well, the obvious choice would be query-string parameters themselves, since they are designed for this. But if you need it as a byte-stream:

如果你想发送键/值对......那么显而易见的选择就是查询字符串参数本身,因为它们是为此而设计的。但是如果你需要它作为字节流:

    var data = new DbConnectionStringBuilder();
    data["foo"] = "abc";
    data["bar"] = "123 + ;la";
    string s = data.ConnectionString;

    byte[] raw = Encoding.UTF8.GetBytes(s);
    string alphaNumeric = Convert.ToBase64String(raw); // send this

    raw = Convert.FromBase64String(alphaNumeric);
    s = Encoding.UTF8.GetString(raw);
    data.ConnectionString = s;
    foreach (string key in data.Keys)
    {
        Console.WriteLine(key + "=" + data[key]);
    }

#2


Why don't you just serialize the data using protobuf-net and pass it through the Session? Or, if it has to be a string, just use XmlSerializer?

为什么不用protobuf-net序列化数据并将其传递给Session?或者,如果它必须是一个字符串,只需使用XmlSerializer?

Personally, passing serialized data through the URL seems really bad to me!

就个人而言,通过URL传递序列化数据对我来说真的很糟糕!

#3


you can serialize your dictionary/hashtable to JSON, and then change it to base64 (just to make it a tad less visible and resolve possible usage of URL characters etc). or you can just URLEncode it.

你可以将你的字典/散列表序列化为JSON,然后将其更改为base64(只是为了让它变得不那么明显并解决URL字符的可能用法等)。或者你可以直接URLEncode它。

#4


You can use standard .Net serialization and serialize your object to a MemoryStream. You can then read out the contents of the MemoryStream as a byte array and use Convert.ToBase64String on the array to get a string representation of it.

您可以使用标准.Net序列化并将对象序列化为MemoryStream。然后,您可以将MemoryStream的内容作为字节数组读出,并使用数组上的Convert.ToBase64String来获取它的字符串表示形式。

To deserialize it you can do the opposite.

要反序列化,你可以做相反的事情。

If you are worried that the serialized object is too large, you can wrap the MemoryStream in a System.IO.Compression.DeflateStream to compress it.

如果您担心序列化对象太大,可以将MemoryStream包装在System.IO.Compression.DeflateStream中以压缩它。

#5


Thank you all, putting it together I wrote a test console app. I was a bit disappointed that the resulting string was so long.

谢谢大家,把它放在一起我写了一个测试控制台应用程序。结果字符串很长,我有点失望。

My example implements a DeflateStream, which for my datasize probably introduces more overhead than it saves with compression. But even without the compression it was still pretty big.

我的示例实现了一个DeflateStream,对于我的datasize可能会引入比压缩保存更多的开销。但即使没有压缩,它仍然很大。

What I was hoping to achieve was to make something slightly more compact (obfuscation for the user was a plus, but not critical) - I suspect that it'd actually be better for me to use a plain old parameterized string. Maybe JSON might be ok, but I'm using ASP.net 2.0, and I don't think that I get a readybaked json serializer there.

我希望实现的是使某些东西稍微更紧凑(对用户进行混淆是一个加分,但并不重要) - 我怀疑使用普通的旧参数化字符串实际上更好。也许JSON可能没关系,但我使用的是ASP.net 2.0,我认为我没有得到一个现成的json序列化器。

Nonetheless, I learnt something new and interesting, so thanks for that!

尽管如此,我学到了一些新的有趣的东西,谢谢!

    static void Main(string[] args)
    {
        Hashtable ht1 = new Hashtable(1);
        ht1.Add("name", "bob");
        Console.WriteLine(ToCompactString(ht1));

        Console.WriteLine();

        string str = "name:bob";
        Console.WriteLine(ToCompactString(str));
        Console.ReadLine();
    }

    private static string ToCompactString(object obj)
    {
        var ms = new MemoryStream();
        var ds = new DeflateStream(ms, CompressionMode.Compress);
        var bf = new BinaryFormatter();

        bf.Serialize(ds, obj);
        byte[] bytes = ms.ToArray();
        ds.Close();
        ms.Close();
        string result = Convert.ToBase64String(bytes);
        return result;
    }