8

yamldotnet と c# を使用して、サード パーティのソフトウェア アプリケーションによって作成されたファイルを逆シリアル化しています。次の YAML ファイルの例は、両方ともアプリケーションから有効です。

#File1
Groups:
  - Name: ATeam
    FirstName, LastName, Age, Height:
      - [Joe, Soap, 21, 184]
      - [Mary, Ryan, 20, 169]
      - [Alex, Dole, 24, 174]

#File2
Groups:
  - Name: ATeam
    FirstName, LastName, Height:
      - [Joe, Soap, 184]
      - [Mary, Ryan, 169]
      - [Alex, Dole, 174]

File2 には Age 列がありませんが、デシリアライザーは各行の 3 番目の値が年齢ではなく高さであることを認識する必要があることに注意してください。このデータは、人のテーブルを表すことになっています。たとえば、File1 の場合、Mary Ryan は 20 歳で、身長は 169 cm です。デシリアライザーは、持っている列を理解し (File2 の場合、FirstName、LastName、および Height のみを持っています)、適切なオブジェクトにデータを適切に格納する必要があります。Mary Ryan の身長は 169cm です。

同様に、プログラムのドキュメントには、列の順序は重要ではないことが記載されているため、以下の File3 は、Height が最初であっても File2 のデータを表すのと同様に有効な方法です。

#File3
Groups:
 - Name: ATeam
   Height, FirstName, LastName:
      - [184, Joe, Soap]
      - [169, Mary, Ryan]
      - [174, Alex, Dole]

いくつか質問があります:

  1. これは標準の YAML ですか? - 同じ行で多数のキーを使用し、その後にコロンと値のリストを続けてデータのテーブルを表す方法については何も見つかりませんでした。
  2. yamldotnet を使用してこれを逆シリアル化するにはどうすればよいですか? それを助けるために私ができる修正はありますか?
  3. yamldotnet を使用できない場合、どうすればよいですか?
4

3 に答える 3

2

他の回答が述べたように、これは有効な YAML です。ただし、ドキュメントの構造はアプリケーションに固有であり、YAML の特別な機能を使用してテーブルを表現することはありません。

YamlDotNet を使用して、このドキュメントを簡単に解析できます。ただし、2 つの困難に遭遇します。1 つ目は、列の名前がキー内に配置されるため、カスタムのシリアル化コードを使用してそれらを処理する必要があることです。2 つ目は、表形式でデータにアクセスできるようにするには、何らかの抽象化を実装する必要があることです。

データを解析して読み取る方法を説明する概念実証を作成しました。

まず、YAML ドキュメントからの情報を保持する型を作成します。

public class Document
{
    public List<Group> Groups { get; set; }
}

public class Group
{
    public string Name { get; set; }

    public IEnumerable<string> ColumnNames { get; set; }

    public IList<IList<object>> Rows { get; set; }
}

次に、型IYamlTypeConverterを解析するために実装します。Group

public class GroupYamlConverter : IYamlTypeConverter
{
    private readonly Deserializer deserializer;

    public GroupYamlConverter(Deserializer deserializer)
    {
        this.deserializer = deserializer;
    }

    public bool Accepts(Type type)
    {
        return type == typeof(Group);
    }

    public object ReadYaml(IParser parser, Type type)
    {
        var group = new Group();

        var reader = new EventReader(parser);
        do
        {
            var key = reader.Expect<Scalar>();
            if(key.Value == "Name")
            {
                group.Name = reader.Expect<Scalar>().Value;
            }
            else
            {
                group.ColumnNames = key.Value
                    .Split(',')
                    .Select(n => n.Trim())
                    .ToArray();

                group.Rows = deserializer.Deserialize<IList<IList<object>>>(reader);
            }
        } while(!reader.Accept<MappingEnd>());
        reader.Expect<MappingEnd>();

        return group;
    }

    public void WriteYaml(IEmitter emitter, object value, Type type)
    {
        throw new NotImplementedException("TODO");
    }
}

最後に、コンバーターをデシリアライザーに登録し、ドキュメントをデシリアライズします。

var deserializer = new Deserializer();
deserializer.RegisterTypeConverter(new GroupYamlConverter(deserializer));

var document = deserializer.Deserialize<Document>(new StringReader(yaml));

ここで完全に機能する例をテストできます

これは概念実証にすぎませんが、独自の実装のガイドラインとして役立つはずです。改善できる可能性があるものは次のとおりです。

  • 無効なドキュメントのチェックと処理。
  • Groupクラスの改善。多分それを不変にして、インデクサーも追加してください。
  • WriteYamlシリアル化のサポートが必要な場合は、メソッドを実装します。
于 2015-06-18T12:31:03.630 に答える
2

遅くなりましたが、最近同じ質問を考えています。

他の人が指摘したように、列名をキーではなく値として記録する方がよいでしょう。また、余分なNameフィールドを削除することもできます。

Groups:
  ATeam:
    Columns: [FirstName, LastName, Height]
    Rows:
      - [Joe, Soap, 184]
      - [Mary, Ryan, 169]
      - [Alex, Dole, 174]

またはあまり明示的でない:

Groups:
  ATeam:
    - [FirstName, LastName, Height]
    - [Joe, Soap, 184]
    - [Mary, Ryan, 169]
    - [Alex, Dole, 174]

これは基本的に YAML 形式の CSV ファイルです。表の行は線として表示されます。

YAML構造のセマンティクスからより理にかなっていると私が思う別の方法は、列名を値に直接関連付けるため、テーブル列を行として表示することです。

Groups:
  ATeam:
    FirstName: [Joe, Mary, Alex]
    LastName: [Soap, Ryan, Dole]
    Height: [184, 169, 174]

Ageこのようにして、残りをまったく変更せずに、行を追加することで余分な列を追加できます。もちろん、余分な行を追加すると、多くの行に影響します。

于 2021-01-29T07:33:30.053 に答える
2

これらはすべて有効な YAML ファイルです。ただし、コンマを含むスカラーキーを、そのキーに関連付けられた値のシーケンスの「列」のYAMLでの記述を構成すると誤解しています。

ファイル 1 では、最上位FirstName, LastName, Age, Heightのキーの値であるシーケンスの最初の要素であるマッピングの単一文字列スカラー キーです。Groupそのままnameです。YAML ではスカラー全体を引用符で囲むことができますが、その必要はありません。

文字列「Firstname」と「Joe」の間に作成した関連付けはYAMLにはありません。キーを解釈するプログラムでその関連付けを行うことができます(キーを分割することにより", ")あなたがやっているようですが、YAMLには知識がありませんその。

したがって、これを賢くしたい場合は、文字列を"FirstName, LastName, Age, Height"自分で分割し、何らかのメカニズムを使用して「サブキー」を使用して、キーに関連付けられているシーケンスにインデックスを付ける必要があります。

これらすべてを理解するのに役立つ場合、以下は最初のファイルの内容の json ダンプです。キーが何で構成されているかが明確にわかります。

{"Groups": [{"FirstName, LastName, Age, Height": [["Joe", "Soap", 21,
   184], ["Mary", "Ryan", 20, 169], ["Alex", "Dole", 24, 174]], 
   "Name": "ATeam"}]}

これには Python ベースのruamel.yamlライブラリ (私が作成者) を使用しましたが、 http: //yaml-online-parser.appspot.com/のようなオンライン コンバーター/チェッカーを使用することもできます。

于 2015-06-17T20:46:18.197 に答える