28

在尝试将命名值元组序列化为 JSON 字符串时,它会丢失分配给项目的名称

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

我期望序列化的值为

{"type":"A","text":"我是动物"}

但实际结果是

{"Item1":"A","Item2":"我是动物"}

有两件事我很想知道

  • 为什么它会这样
  • 如何获得预期的输出
4

3 回答 3

25

如何获得预期的输出

像这样的东西:

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

如果您正在寻找类似的简洁方法,应该可以工作。虽然不使用ValueTuples (但匿名类型)在引擎盖下;这是我将您的问题解释为“如何在不完全声明类等的情况下生成这个预期的 JSON”</p>

于 2019-01-28T08:41:07.283 回答
18

这些名称是一个编译器技巧。如果您查看定义,ValueTuple您会发现它的字段名称只是Item1,Item2等。

由于在JsonConvert.SerializeObject分配可以在编译期间使用的名称之前就已经编译好,因此它无法恢复名称。

方法参数/返回类型用属性修饰,这些属性指示方法签名包含ValueTuples 时要使用的名称。这允许稍后编写的代码再次“看到”编译器玩弄技巧的名称,但这是“错误的方式”在这里很有用。

如何获得预期的输出

如果字段/属性的名称非常重要,请引入显式类型。

于 2019-01-28T08:23:21.833 回答
3

如何获得预期的输出

在@Caius 答案中使用显式自定义类型或匿名类。

或者根本不为它创建特殊类型(因为匿名类型编译器会在后台为您生成类)并使用JObject动态创建 json:

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

或为其使用索引器和初始化语法

var createdJson = new JObject()
{
    ["type"] = "A",
    ["text"] = "I am an animal"
};
var cnvValue = createdJson.ToString();
于 2019-02-03T23:15:43.260 回答