【问题标题】:Custom string deserialization自定义字符串反序列化
【发布时间】:2014-03-28 14:11:12
【问题描述】:

我有一个以前从未使用过的自定义数据字符串。它看起来类似于 JSON,但它有一个独特的结构,我无法弄清楚如何正确反序列化。

这是一个示例字符串,显示了我正在处理的简单模拟结构:

description="
has_table=TRUE
scale=1.0
apply_scale=FALSE
custom_units=1
style{
 0{
  name="TestName1
  description="
  color=-1006632961
  size=0.5
  adaptive=TRUE
 }
 1{
  name="TestName2
  description="
  color=-1
  size=0.75
  adaptive=TRUE
 }
 2{
  name="TestName3
  description="
  color=-1006632354
  size=1.5
  adaptive=FALSE
 }
 size_table{
 0=0.0
 1=0.1
 2=0.2
 3=0.25
 10=0.35
 13=0.5
 17=0.75
 20=1.0
 21=1.25
 22=1.5
}

到目前为止,我一直在手动滚动自己的课程。上面的字符串最终会反序列化为以下类:

public class ExampleStyleList
{
    public string Description {get; set;}
    public bool HasTable {get; set;}
    public double Scale {get; set;}
    public bool ApplyScale {get; set;}
    public int CustomUnits {get; set;}
    public IList<double> Sizes {get; set;}

    protected IList<ExampleStyle> InnerStyles {get; set;}
}

public class ExampleStyle
{
    public string Name {get; set;}
    public string Description {get; set;}
    public System.Drawing.Color Color {get; set;}
    public double Size {get; set;}
    public bool Adaptive {get; set;}
}

现在我正在手动将所有内容反序列化到我的类中;一次读取一行并查找括号、构建字典以及查找事物的静态名称。它非常丑陋,而且效率不高,更不用说可能超级脆弱。我觉得我首先从这种奇怪的格式转换为 XML 会受益,我可以只使用 XMLSerializer,但我真的是在画一个空白。

【问题讨论】:

  • 添加你的类结构,我还会创建一个 size_table 类,因为它将你的尺寸链接到一个 ID,而不是双精度的 ILIST

标签: c# xml json serialization deserialization


【解决方案1】:

我最终只是手动模仿了 XML 节点层次结构,并且对结果非常满意。一旦我将我的类设置为从自定义节点类继承,实现反序列化就非常简单了。当我们遍历这些行时,或者我们正在向当前节点添加一个值,或者我们正在构建一个子节点。反序列化是从内部构造函数调用的,所以这里有递归,乍一看可能并不明显。

    public static void Deserialize(PiaNode node)
    {
        if (node == null)
            throw new ArgumentNullException("Node");

        if (String.IsNullOrEmpty(node.InnerData))
            throw new ArgumentNullException("InnerData");

        var dataLines = node.InnerData.Split(new char[]{'\r', '\n'},
                                        StringSplitOptions.RemoveEmptyEntries);

        for (int i = 0; i < dataLines.Length; i++)
        {
            var curLine = dataLines[i];
            if (curLine.Contains('='))
            {
                var value = _getValue(curLine);

                if (!node.Values.ContainsKey(value.Key))
                    node.Values.Add(value.Key, value.Value);
                else
                    node.Values[value.Key] = value.Value;
            }
            else if (curLine.Contains('{'))
            {
                var bracketCount = 1;
                var nodeBuilder = new StringBuilder();
                var n = i + 1;
                var subLine = string.Empty;

                while (bracketCount != 0)
                {
                    subLine = dataLines[n++];
                    bracketCount += subLine.Contains('{')
                        ? 1 : subLine.Contains('}')
                        ? -1 : 0;

                    if (bracketCount != 0)
                        nodeBuilder.AppendLine(subLine);
                }

                var childNode = new PiaNode(nodeBuilder.ToString())
                {
                    NodeName = curLine.Trim().TrimEnd('{'),
                    Parent = node
                };

                node.ChildNodes.Add(childNode);
                i = n - 1;
            }
        }
    }

    public static KeyValuePair<string, string> _getValue(string valueString)
    {
        var prop = valueString.TrimEnd(new char[] {'\r', '\n'}).Split('=');
        return new KeyValuePair<string,string>(prop[0].Trim(), prop[1].TrimStart('\"'));
    }

我没有尝试在反序列化过程中设置节点继承类的属性(我之前做过),而是将属性的 setter/getter 直接链接到反序列化期间填充的字典。

【讨论】:

    猜你喜欢
    • 2019-02-24
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多