web-dev-qa-db-ja.com

シリアル化するとValueTuplesのプロパティ名が失われる

名前付き値タプルをJSON文字列にシリアル化しようとすると、アイテムに割り当てられた名前が失われます

(string type, string text) myTypes = ("A", "I am an animal");
var cnvValue = JsonConvert.SerializeObject(myTypes);

私はシリアル化された値を期待しています

{"タイプ": "A"、 "テキスト": "私は動物です"}

しかし実際の結果は

{"Item1": "A"、 "Item2": "私は動物です"}

私が知りたいことが2つあります

  • なぜそれはそのように振る舞うのですか
  • 期待される出力を取得する方法
22
mdowes

期待される出力を取得する方法

このようなもの:

var myTypes = new{ type = "A", text = "I am an animal"};
var cnvValue = JsonConvert.SerializeObject(myTypes);

同様に簡潔なアプローチを探している場合は、機能するはずです。ただし、内部ではValueTuples(ただし匿名型)は使用しません。これはあなたの質問を「クラスを宣言するなどの最大限の努力をせずに、どのようにしてこの期待されるJSONを生成できるでしょうか」と解釈しています。

18
Caius Jard

名前はコンパイラのトリックです。 ValueTuple の定義を見ると、フィールド名がItem1Item2などであることがわかります。

JsonConvert.SerializeObjectは、yourコンパイル中に使用できる名前を割り当てる前にコンパイルされているため、名前を復元できません。

メソッドパラメータ/戻り値の型は、メソッドのシグネチャにValueTuplesが含まれる場合に使用される名前を示す attributes で装飾されています。これにより、後で作成されたコードがコンパイラーが再びトリックを「見る」ことができるようになりますが、ここではこれが「間違った方法」で非常に役立ちます。

期待される出力を取得する方法

フィールド/プロパティの名前が非常に重要な場合は、明示的なタイプを導入します。

15

期待される出力を取得する方法

@Caiusの回答のように、明示的なカスタムタイプまたは匿名クラスを使用します。

または、そのための特別なタイプをまったく作成しないでください(匿名タイプのコンパイラがバックグラウンドでクラスを生成するため)。 JObject を使用して動的にjsonを作成します。

var myTypesJson = new JObject(
    new JProperty("type", "A"), 
    new JProperty("text", "I am an animal")
);
var cnvValue = myTypesJson.ToString();

または、インデクサーと初期化 syntax を使用します:

var createdJson = new JObject()
{
    ["type"] = "A",
    ["text"] = "I am an animal"
};
var cnvValue = createdJson.ToString();
2