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

Posted

技术标签:

【中文标题】使用 C# 返回具有重复键的 Json 对象【英文标题】:Return Json object with Duplicate Keys using C# 【发布时间】:2017-07-12 02:14:49 【问题描述】:

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

之前我用过字典

例如:

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"
    

但我需要一个唯一密钥(即重复密钥),所以我将Dictionary&lt;string, string&gt; 更改为List&lt;KeyValuePair&lt;string, string&gt;&gt;

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"
    

【问题讨论】:

也许您需要与您的客户交谈并向他们解释这是一个愚蠢的要求,可能会在未来引入各种问题? 是的,从技术上讲,这是有效的 JSON,但是,根据规范,它的 含义 是忽略前面的重复键。因此,您的在线工具中的警告。如果您关心数据的完整性,则 JSON 无效。由于您确实关心完整性,因此您不能再将其称为 JSON。它现在是您自己的自定义格式,恰好类似于 JSON 几天后,我们将看到来自这家公司的另一位开发人员的问题:“如何解析带有重复键的 JSON?我需要所有值,但只需要我的库返回最后一个。” 哦,好吧... @B.Balamanigandan:我说的是可怜的家伙,他必须解析你正在创建的输出,而不是你。 :-) 任何时候你发现自己说“我需要一个重复的密钥”,我认为是时候重新考虑你的设计了。 【参考方案1】:

,这是不可能的。

这将是无效的* JSON:


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

你可以查看这个here:

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

*Depending on what you call valid

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


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

ECMA-262:

在对象内有重复名称字符串的情况下, 同一个键的词法前面的值将被覆盖。

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

【讨论】:

只是为了扩展这一点,重要的是要记住 JSON 代表一个 对象。您无法在我知道的任何其他 OO 概念中创建具有重复属性名称的对象。当然它会编译没有错误(尽管有警告),但它实际上不会可用。 我假设这里的 VALID 意味着只有 json 字符串的语法是有效的,说打开和关闭是正确的......等等 @Luminous_Dev 真正让我好奇的是,API 究竟是如何使用带有重复键的 JSON 来制作可用的东西... 您的要求毫无意义,只要您需要以编程方式使用 JSON @B.Balamanigandan。你真的应该使用一个简单的 errorMessage 字段,它是一个错误消息数组。这就是xy 的问题。 @B.Balamanigandan,这个要求是不可能的。如果您需要有关 StringBuilder 的帮助,请阅读文档。但这不是你应该这样做的方式,我不会为你写它。这将是一种广泛的方式。通过与给您要求的人交谈来更改要求。与此人沟通为什么这是一个不好的要求。在此处参考您的问题。但这就是我本次讨论的一部分。对于那个很抱歉。我也有我的项目需要完成。也许其他人编写了适合您需求的解决方案。请随意对我的回答投反对票。【参考方案2】:

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

这是您的 X:您想要获取的 JSON 格式:


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

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

但是,有一种非常简单的方法可以获取所有错误消息。您只需将您期望的 JSON 改为 this 即可:


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

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


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

这样,当您将 JSON 加载到您的 C# 代码中时,它总是具有相同的类型,Dictionary&lt;string,List&lt;string&gt;&gt;,无论是一个错误还是多个错误。

这就是你的 XY 问题中的 Y。与其把头撞在“我想在 JSON 中有重复的键”的墙上,不如想办法绕过墙:有一个带有值列表的键。现在您可以做您真正需要的事情,即从表单中获取所有错误消息,每条错误消息只需一个键名。

【讨论】:

这对我的生活总体有帮助

以上是关于使用 C# 返回具有重复键的 Json 对象的主要内容,如果未能解决你的问题,请参考以下文章

从JSON中获取重复的对象键的值,并只用一个键替换返回。

具有数据框或 Excel 文件的重复键的 JSON 文件

将字符串转换为具有重复键的对象到数组

C#返回具有匹配属性的对象列表[重复]

将反序列化的 JSON 对象保存到具有重复子实体的数据库

如何在 JSON 对象中获取键的值 [重复]