自定义字符串反序列化

时间:2014-03-28 14:11:12

标签: c# xml json serialization deserialization

我有一个我从未使用过的自定义数据字符串。它似乎与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,但是我真的是空白了。

1 个答案:

答案 0 :(得分:0)

我最终只是手动模仿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直接链接到反序列化过程中填充的字典。