首页 > 解决方案 > 有没有办法将序列视为 yamldotnet 中的单个映射?

问题描述

我有一个第三方 YAML 数据,我需要对其进行反序列化修改然后序列化并发回。问题是他们的数据被格式化,所以每个条目都是它自己的序列。我能够想出一个可以序列化数据的类型转换器,但是在为此编写序列化程序之前,我想看看是否有更好的方法来解决这个问题。

YAML:


    ---
    Message:
      - Name: GENCBL
      - Style: 1x7 Western Fixed
      - PrintDelay: 0
      - PrintCount: 90
      - Orientation:
          - Rotation: 0
          - HFlip: False
          - VFlip: False
      - Printer:
          - Type: 8900
          - Pitch:
              - Horizontal: 320
              - VerticalAdj: 0
      - Line:
          - Field:
              - Name: Field 1
              - Type: Text
              - Visibility: True
              - Rotation: 0
              - Negative: False
              - Locale: en_GB
              - Boldness: 1
              - Pos:
                  - X: 25
                  - Y: 0
              - Font:
                  - Name: Universal
                  - Size: 7
                  - Units: Drops
                  - Rotation: 0
              - Parameters:
                  - Text: FEET
          - Field:
              - Name: Field 1
              - Type: Text
              - Visibility: True
              - Rotation: 0
              - Negative: False
              - Locale: en_GB
              - Boldness: 1
              - Pos:
                  - X: 502
                  - Y: 0
              - Font:
                  - Name: Universal
                  - Size: 7
                  - Units: Drops
                  - Rotation: 0
              - Parameters:
                  - Text: ---
          - Field:
              - Name: Field 1
              - Type: Date
              - Visibility: True
              - Rotation: 0
              - Negative: False
              - Locale: en_GB
              - Boldness: 1
              - Pos:
                  - X: 968
                  - Y: 0
              - Font:
                  - Name: Universal
                  - Size: 7
                  - Units: Drops
                  - Rotation: 0
              - Parameters:
                  - Format: ""%MM%""
                  - Offset:
                      - Time: 0:0
    ...

类型转换器:

public class SequenceConverter<T> : IYamlTypeConverter where T: new()
{

    /// <summary>
    /// Gets a value indicating whether the current converter supports converting the specified type.
    /// </summary>
    public bool Accepts(Type type)
    {
        return typeof(T).IsAssignableFrom(type);
    }

    /// <summary>Reads an object's state from a YAML parser.</summary>
    public object ReadYaml(IParser parser, Type type)
    {
        var baseObject = new T();

        parser.Consume<SequenceStart>();

        while (parser.Current is MappingStart)
        {
            ParseNextField(parser, baseObject);
        }

        parser.Consume<SequenceEnd>();

        return baseObject;
    }

    private static void ParseNextField(IParser parser, object current)
    {
        parser.Consume<MappingStart>();
        Scalar key = parser.Consume<Scalar>();

        var keyValue = key.Value;

        if (keyValue == "Offset")
        {
            keyValue = parser.Current is Scalar ? "OffsetString" : "OffsetObject";
        }
        System.Reflection.PropertyInfo propInfo = current.GetType().GetProperty(keyValue);

        if (propInfo != null)
        {
            if (parser.TryConsume(out Scalar value))
            {
                if (propInfo.PropertyType.IsValueType || propInfo.PropertyType == typeof(string))
                {
                    propInfo.SetValue(current, Convert.ChangeType(value.Value, propInfo.PropertyType));
                }
            }
            else if (parser.TryConsume<SequenceStart>(out _))
            {
                if (typeof(IList).IsAssignableFrom(propInfo.PropertyType))
                {
                    if (propInfo.GetValue(current) == null)
                    {
                        object propInstance = Activator.CreateInstance(propInfo.PropertyType);
                        propInfo.SetValue(current, propInstance);
                    }

                    var list = propInfo.GetValue(current) as IList;
                    var childInstance = Activator.CreateInstance(propInfo.PropertyType.GetGenericArguments().First());
                    list?.Add(childInstance);
                    while (parser.Current is MappingStart)
                    {
                        ParseNextField(parser, childInstance);
                    }
                }
                else
                {
                    object propInstance = Activator.CreateInstance(propInfo.PropertyType);
                    propInfo.SetValue(current, propInstance);


                    while (parser.Current is MappingStart)
                    {
                        ParseNextField(parser, propInstance);
                    }
                }

                parser.Consume<SequenceEnd>();
            }
        }

        parser.Consume<MappingEnd>();
    }

    /// <summary>
    /// Writes the specified object's state to a YAML emitter.
    /// </summary>
    public void WriteYaml(IEmitter emitter, object value, Type type)
    {
        throw new NotImplementedException();
    }
}

序列化类:

public class Message
        {
            public string Name { get; set; }
            public string Style { get; set; }
            public int PrintDelay { get; set; }
            public int PrintCount { get; set; }
            public Orientation Orientation { get; set; }
            public PrinterDetails Printer { get; set; }
            public List<Line> Line { get; set; }
        }

        public class Orientation
        {
            public int Rotation { get; set; }
            public bool HFlip { get; set; }
            public bool VFlip { get; set; }
        }

        public class PrinterDetails
        {
            public string Type { get; set; }
            public Pitch Pitch { get; set; }
        }

        public class Pitch
        {
            public int Horizontal { get; set; }
            public int VerticalAdj { get; set; }
        }

        public class Line
        {
            public List<Field> Field { get; set; }
        }

        public class Field
        {
            public string Name { get; set; }
            public string Type { get; set; }
            public bool Visibility { get; set; }
            public int Rotation { get; set; }
            public bool Negative { get; set; }
            public string Locale { get; set; }
            public int Boldness { get; set; }
            public Position Pos { get; set; }
            public Font Font { get; set; }
            public Parameters Parameters { get; set; }
        }

        public class Parameters
        {
            public string Format { get; set; }
            public string Text { get; set; }
            public string Start { get; set; }
            public string Stop { get; set; }
            public int Step { get; set; }
            public int Repeat { get; set; }
            public int CurrentRepeat { get; set; }
            public string OffsetString { get; set; }
            public Offset OffsetObject { get; set; }

        }

        public class Offset
        {
            public string Time { get; set; }
        }

        public class Position
        {
            public int X { get; set; }
            public int Y { get; set; }
        }

        public class Font
        {
            public string Name { get; set; }
            public int Size { get; set; }
            public string Units { get; set; }
            public int Rotation { get; set; }
        }

标签: yamldotnet

解决方案


推荐阅读