将填充了位和字节的 ushort[] 反序列化为自定义对象

Posted

技术标签:

【中文标题】将填充了位和字节的 ushort[] 反序列化为自定义对象【英文标题】:Deserialize ushort[] filled with bits and bytes to custom object 【发布时间】:2021-01-04 18:01:05 【问题描述】:

我有一个包含 450 多个成员的 ushort[],其中填充了重复的 12 个布尔值和 1 个字节值,如下所示:

我需要从数组中获取Person对象或者从List<Person>获取ushort[],所以基本上我需要对这个ushort[]进行反序列化和序列化。

为了轻松解析它,我想也许我可以将它反序列化为像这样的单个对象,但在它看起来很糟糕后放弃了:

class Person

    public bool Property0  get; set; 
    public bool Property1  get; set; 
    public bool Property2  get; set; 
    public bool Property3  get; set; 
    public bool Property4  get; set; 
    public bool Property5  get; set; 
    public bool Property6  get; set; 
    public bool Property7  get; set; 
    public bool Property8  get; set; 
    public bool Property9  get; set; 
    public bool Property10  get; set; 
    public bool Property11  get; set; 
    public byte Property12  get; set; 



private List<Person> Deserialize(ushort[] array)

    var personList = new List<Person>();
    Person person1 = new Person();
    Person person2 = new Person();
    for (int i = 0; i < array.Length; i++)
    
        BitArray bitArray = new BitArray(array[i]);

        if (i % 3 == 0)
        
            person1 = new Person();
            person1.Property0 = bitArray[0];
            person1.Property1 = bitArray[1];
            person1.Property2 = bitArray[2];
            person1.Property3 = bitArray[3];
            person1.Property4 = bitArray[4];
            person1.Property5 = bitArray[5];
            person1.Property6 = bitArray[6];
            person1.Property7 = bitArray[7];
            person1.Property8 = bitArray[8];
            person1.Property9 = bitArray[9];
            person1.Property10 = bitArray[10];
            person1.Property11 = bitArray[11];
        

        if (i % 3 == 1)
        
            byte[] bytes = new byte[1];
            bitArray.CopyTo(bytes, 0);
            person1.Property12 = bytes[0];
            
            personList.Add(person1);

            person2 = new Person();
            person2.Property0 = bitArray[0];
            person2.Property1 = bitArray[1];
            person2.Property2 = bitArray[2];
            person2.Property3 = bitArray[3];
            person2.Property4 = bitArray[4];
            person2.Property5 = bitArray[5];
            person2.Property6 = bitArray[6];
            person2.Property7 = bitArray[7];
        

        if (i % 3 == 2)
        
            person2.Property8 = bitArray[8];
            person2.Property9 = bitArray[9];
            person2.Property10 = bitArray[10];
            person2.Property11 = bitArray[11];

            byte[] bytes = new byte[1];
            bitArray.CopyTo(bytes, 5);
            person2.Property12 = bytes[0];

            personList.Add(person2);
        
    
    return personList;

我怎样才能让这个漂亮?

我使用属性来序列化/反序列化 json,但库可以完成这项工作,是否有类似的东西用于数组反序列化?

提前致谢。

【问题讨论】:

您能否更好地解释一下ushort[] 和起始索引部分?抱歉,在我看来,有些部分丢失了,即使是您向我们展示的代码也没有告诉我们您想要做什么。 使用的BitArray 构造函数重载创建了一个填充有false 值的实例。因此,创建它然后从中复制false 是没有意义的。只需使用值false0 填写所有person1person2 属性。 我试图简化问题并从中删除不必要的信息,您可以再检查一下吗?基本上我只需要序列化/反序列化一个填充有 12 位 1 字节值的 ushort[]。 再次:new BitArray(array[i]) 创建空的 bitArray 填充有 false 值。您不要在代码中使用 ushort 数组值。 我没有说我的代码有效,当我搜索时我发现了 BitArray 并尝试编写示例方法来显示我的意图以及我试图解决我的问题的方法。该代码基本上意味着我只是没有在 Stack Overflow 中提出问题而没有至少进行研究。 【参考方案1】:

如果我必须进行这样的反序列化,我会使用以下方法作为开始并对其进行改进。

首先,我会将Person 类更新为:

public class Person

    private readonly BitArray booleanPropertyBits;
    private readonly byte bit16To23;
    
    public Person(byte byte1, byte byte2, byte byte3)
    
        booleanPropertyBits = new BitArray(new byte[]  byte1, byte2 );
        bit16To23 = byte3;
    

    public bool Property0 => booleanPropertyBits[0];
    public bool Property1 => booleanPropertyBits[1];
    public bool Property2 => booleanPropertyBits[2];
    public bool Property3 => booleanPropertyBits[3];
    public bool Property4 => booleanPropertyBits[4];
    public bool Property5 => booleanPropertyBits[5];
    public bool Property6 => booleanPropertyBits[6];
    public bool Property7 => booleanPropertyBits[7];
    public bool Property8 => booleanPropertyBits[8];
    public bool Property9 => booleanPropertyBits[9];
    public bool Property10 => booleanPropertyBits[10];
    public bool Property11 => booleanPropertyBits[11];
    public byte Property12 => bit16To23;

之后,我会有一个辅助类,它将 ushort[] 转换为 byte[],例如:

public static class ByteStream

    public static IEnumerable<byte> From(ushort[] array)
    
        foreach (var number in array)
        
            var bytes = BitConverter.GetBytes(number);
            foreach (var b in bytes)
            
                yield return b;
            
        
    

最后,我会使用辅助方法以下列方式读取值:

private List<Person> Deserialize(ushort[] array)

    var bytes = ByteStream.From(array).ToArray();
    var retVal = new List<Person>();

    for (int i = 0; i < bytes.Length; i += 3)
    
        var person = new Person(bytes[i], bytes[i + 1], bytes[i + 2]);
        retVal.Add(person);
    

    return retVal;

不是一个完整的解决方案,但可以通过添加验证检查和一些性能调整来开始和改进。

【讨论】:

@Caguryay 有帮助吗?

以上是关于将填充了位和字节的 ushort[] 反序列化为自定义对象的主要内容,如果未能解决你的问题,请参考以下文章

Jackson 将 YAML 文件反序列化为 Map(没有自定义反序列化器)

如何从不使用 XElement 的自定义 XML 序列化/反序列化为 `Dictionary<int, string>`?

如何通过 gson 将 json 反序列化为嵌套的自定义地图?

将 JSON 包反序列化为具有自定义属性名称的类

将位置坐标的 Mongo BSON 数组反序列化为自定义 C# 类

使用 XmlSerializer 将 XML 反序列化为类型