使用 C 返回带有重复键的 Json 对象#

Return Json object with Duplicate Keys using C#

提问人:B.Balamanigandan 提问时间:2/22/2017 最后编辑:davidsbroB.Balamanigandan 更新时间:10/9/2021 访问量:11208

问:

我正在使用 WEB API 接收来自客户端应用程序的请求以保存联系人信息,并且仅当数据出现错误时才需要发送错误消息;否则没有待办事项

之前我使用了 Dictionary<string, string>

例如:

Dictionary<string, string> error = new Dictionary<string, string>
{
    {"SaveContactMethod_1", "FirstName Invalid"},
    {"SaveContactMethod_2", "LastName Invalid"},
    {"SaveContactMethod_3", "MiddleName Invalid"},
}

相应的 JSON 对象是

{
    "error" : {
        "SaveContactMethod_1":"FirstName Invalid",
        "SaveContactMethod_2":"LastName Invalid",
        "SaveContactMethod_3":"MiddleName Invalid"
    }
}

但是我需要一个 UNIQUE 键(即重复键),所以我将Dictionary<string, string>List<KeyValuePair<string, string>>

List<KeyValuePair<string, string>> error = new List<KeyValuePair<string, string>>
{
    new KeyValuePair<string, string>("SaveContactMethod", "FirstName Invalid"),
    new KeyValuePair<string, string>("SaveContactMethod", "LastName Invalid"),
    new KeyValuePair<string, string>("SaveContactMethod", "MiddleName Invalid"),
}

相应的 JSON 对象是

{
    "error" : [
        { "key":"SaveContactMethod", "value":"FirstName Invalid" },
        { "key":"SaveContactMethod", "value":"LastName Invalid" },
        { "key":"SaveContactMethod", "value":"MiddleName Invalid" }
    ]
}

我的要求:我需要添加一个重复键,我需要像字典一样的 Json 输出。

预期输出:JSON

{
    "error" : {
        "SaveContactMethod":"FirstName Invalid",
        "SaveContactMethod":"LastName Invalid",
        "SaveContactMethod":"MiddleName Invalid"
    }
}
C# JSON 字典 键值

评论

24赞 Pekka 2/22/2017
也许你需要和你的客户谈谈,向他们解释这是一个愚蠢的要求,可能会在未来引入各种问题?
49赞 Rob 2/22/2017
是的,从技术上讲,这是有效的 JSON,但是,根据规范,这意味着前面的重复键将被忽略。因此,您的在线工具中的警告。如果您关心数据的完整性,则 JSON 无效。由于您确实关心完整性,因此您不能再将其称为 JSON。它现在是你自己的自定义格式,恰好类似于 JSON
54赞 Heinzi 2/23/2017
几天后,我们将看到这家公司的另一位开发人员提出的一个问题:“如何解析具有重复键的 JSON?我需要所有值,但我的库只返回最后一个值。哦,好吧......
20赞 Heinzi 2/23/2017
@B.Balamanigandan:我说的是那个可怜的家伙,他必须解析你正在创建的输出,而不是关于你。:-)
33赞 JLRishe 2/23/2017
每当你发现自己说“我需要一把重复的钥匙”时,我认为是时候重新考虑你的设计了。

答:

107赞 Christian Gollhardt 2/22/2017 #1

,这是不可能的。

这将是无效的* JSON:

{
    "error" : {
        "SaveContactMethod":"FirstName Invalid",
        "SaveContactMethod":"LastName Invalid",
        "SaveContactMethod":"MiddleName Invalid"
    }
}

您可以在此处查看:

Warning:Duplicate key, names should be unique.[Code 23, Structure 9]
Warning:Duplicate key, names should be unique.[Code 23, Structure 13]

*取决于您所说的有效

如果你真的想走这条路,根据 RFC 4627,你可以使用 StringBuilder 类。


既然你似乎不明白,取决于你所说的有效意味着什么。

ECMA-262:

如果对象中存在重复的名称字符串, 同一键的词法前面的值应被覆盖。

这意味着:如果你得到三个',你只需要ECMA脚本(JS)。使用 c# 序列化,这甚至是不可能的。您需要为其编写自己的 JsonSerializer。SaveContactMethod"MiddleName Invalid"

评论

16赞 Eric Sondergard 2/22/2017
为了扩展这一点,重要的是要记住 JSON 表示一个对象。在我所知道的任何其他 OO 概念中,您都无法创建具有重复属性名称的对象。当然,它会编译而不会出错(尽管有警告),但它实际上不可用。
1赞 Luminous_Dev 2/22/2017
我假设这里的 VALID 含义只有 json 字符串的语法是有效的,说明打开和关闭是正确完成的......等
4赞 Eric Sondergard 2/22/2017
@Luminous_Dev 我在这里最好奇的是,API 到底是如何从具有重复键的 JSON 中制作出可用的东西的......
23赞 Christian Gollhardt 2/22/2017
只要您需要以编程方式使用 JSON @B.Balamanigandan,您的要求就无关紧要。您确实应该使用一个简单的 errorMessage 字段,即错误消息数组。这就是 xy 问题。
41赞 Christian Gollhardt 2/22/2017
@B.Balamanigandan,要求是不可能的。如果您需要有关 StringBuilder 的帮助,请阅读文档。但这不是你应该这样做的方式,我不会为你写。这将是广泛的方式。通过与提出要求的人交谈来更改要求。与此人沟通为什么这是一个糟糕的要求。请在此处参考您的问题。但这就是我这次讨论的结束。对不起。我也有我的项目需要完成。也许其他人编写了适合您需求的解决方案。请随时对我的答案投反对票。
115赞 rmunn 2/23/2017 #2

你有一个经典的“XY”问题。你问过“我如何做X”,但你真的需要做Y,你认为X是达到Y的唯一方法——但X要么是不可能的,要么非常困难。通过稍微改变你的要求,你可以以不同的方式到达 Y,但你还没有看到这一点,因为你被困在 X 上。

下面是你的 X:你想要获取的 JSON 格式:

{
    "error" : {
        "SaveContactMethod":"FirstName Invalid",
        "SaveContactMethod":"LastName Invalid",
        "SaveContactMethod":"MiddleName Invalid"
    }
}

正如其他人所说,这将丢弃所有错误消息,但将它加载到 C# 代码中时除外。

但是,有一种非常简单的方法可以获取所有错误消息。你只需要更改你期望的 JSON 如下所示:

{
    "error" : {
        "SaveContactMethod": [
            "FirstName Invalid",
            "LastName Invalid",
            "MiddleName Invalid"
        ]
    }
}

如果只有一条错误消息,则仍应使用列表

{
    "error" : {
        "SaveContactMethod": [
            "FirstName Invalid"
        ]
    }
}

这样,当您将 JSON 加载到 C# 代码中时,无论存在一个错误还是多个错误,它都将始终具有相同的类型。Dictionary<string,List<string>>

这就是 XY 问题中的 Y。与其把头撞在“我想在JSON中使用重复的键”的墙上,不如找到一种方法绕过墙:使用一个带有值列表的键。现在,您可以执行真正需要的操作,即从表单中获取所有错误消息,每个错误消息只需一个键名称。