Json.NET(Newtonsoft.Json)- 两个具有相同名称的“属性”?

5

我正在使用.NET Framework 3.5的C#进行编码。

我试图解析一些Json到一个JObject中。

以下是Json:

{
    "TBox": {
        "Name": "SmallBox",
        "Length": 1,
        "Width": 1,
        "Height": 2 },
    "TBox": {
        "Name": "MedBox",
        "Length": 5,
        "Width": 10,
        "Height": 10 },
    "TBox": {
        "Name": "LargeBox",
        "Length": 20,
        "Width": 20,
        "Height": 10 }
}

当我尝试将此Json解析为JObject时,JObject仅知道LargeBox的信息。SmallBox和MedBox的信息丢失了。显然,这是因为它将“TBox”解释为属性,并且该属性被覆盖了。
我从用Delphi编写的服务中接收到此Json。我正在尝试为该服务创建C#代理。在Delphi方面,“TBox”被理解为返回的对象的类型。然后,内部属性(“Name”,“Length”,“Width”,“Height”)被视为常规属性。
我可以序列化和反序列化具有名称,长度,宽度和高度属性的自定义'TBox'对象。那很好。
我想做的是以一种能够提取以下三个Json字符串的方式遍历所有TBox部分。
{
    "Name": "SmallBox",
    "Length": 1,
    "Width": 1,
    "Height": 2 }

第二点:

{
    "Name": "MedBox"
    "Length": 5,
    "Width": 10,
    "Height": 10 }

第三点:

{
    "Name": "LargeBox"
    "Length": 20,
    "Width": 20,
    "Height": 10 }

一旦我有了这些字符串,我可以随心所欲地进行序列化和反序列化。

我发现Newtonsoft.Json非常好用。如果可以避免的话,我真的不想去破坏其他框架。

任何帮助都将不胜感激。

对于服务器可以做出的更改,我的输入非常有限。

2个回答

8
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

JsonTextReader jsonReader = new JsonTextReader(reader);
jsonReader.Read();
while(jsonReader.Read())
{
    if(jsonReader.TokenType == JsonToken.StartObject)
    {
        JObject tbox = JObject.Load(jsonReader);
    }
}

然而,请注意RFC中指出,“对象内的名称应该是唯一的”,因此如果可能的话,建议更改格式。
编辑:这里有一个替代设计,它没有重复的键。
[
    {
        "TBox": {
            "Width": 1,
            "Length": 1,
            "Name": "SmallBox",
            "Height": 2
        }
    },
    {
        "TBox": {
            "Width": 10,
            "Length": 5,
            "Name": "MedBox",
            "Height": 10
        }
    },
    {
        "TBox": {
            "Width": 20,
            "Length": 20,
            "Name": "LargeBox",
            "Height": 10
        }
    }
]

2
@Ubiquitous,我从未说它违反了RFC。但是它不直观,我不一定同意这是打破它的原因。还有其他设计可以提供类型信息而不需要重复键。 - Matthew Flaschen
5
JSON中的对象是一个名称/值集合,而这个JSON在误用名称。在本例中,Json.NET的JObject正是当浏览器提供重复属性时所做的:使用最后一个值。最好的解决方案是将JSON更改为具有包装对象和类型名称属性以及值属性的属性或者将类型作为值对象的特殊属性添加到JSON中。 - James Newton-King
3
冷静一点——我只是在提出自己的意见,试图帮助你,而不是批评你。在这种情况下,用户就是开发人员。开发人员通常使用名/值集合的JSON对象进行工作。JSON主页-http://json.org/-将它们定义为一个名/值集合。再次强调,您并没有违反规范,但破坏了用户(开发人员)的期望。如果您有充分的理由来构建JSON的结构,那么那样做也是可以的,只需注意这样做会产生更多类似于消费者这个问题的帮助请求。 - James Newton-King
1
@Deltics - 规范说明名称应该是唯一的。是的,我知道SHOULD和MUST之间的区别。规范没有说明解析器应该如何处理重复的键 - 这就是我所指的歧义所在。规范化的JSON解析器JavaScript会怎么做?它会将它们丢弃。除非你深入到令牌流的级别,否则Newtonsoft也会这样做,但不应要求任何人这样做才能读取您的值。无论如何,我很高兴我永远不必与你合作。 OP有我的同情。 - Joel Mueller
2
哇,我猜你用那个“END. FINAL.”的东西向我展示了。做得好。我想,json.org说JavaScript“解析”JSON文本只是一种比喻吧。如果(语言==“JavaScript”)parser = false?我想JavaScript在遇到重复名称时不会抛出错误并不会使你关于解析器的说法无效,因为JavaScript从来没有解析过任何东西。重新定义的工作做得很好。我向大师鞠躬。但是,如果你想让不同意你的人闭嘴,你忘记了一个重要的短语:END. FINAL. TIMES INFINITY. 手指放在耳朵上 Lalala... - Shawn Grigson
显示剩余30条评论

4

如果我没记错的话,正确的答案是你的输入实际上不是JSON格式的。所以,使用JSON解析器来解析它可能行不通。

也许你无法控制输入的来源,那么我建议使用正则表达式或其他方法来预处理字符串。将其转换成类似以下的格式:

{"TBoxes":
    [
        {
            "Name": "SmallBox",
            "Length": 1,
            "Width": 1,
            "Height": 2 
        },
        {
            "Name": "MedBox",
            "Length": 5,
            "Width": 10,
            "Height": 10 
        },
        {
            "Name": "LargeBox",
            "Length": 20,
            "Width": 20,
            "Height": 10 
        }
    ]
}

把它当作数组来处理。

我尝试使用正则表达式,但发现它很难。在一些真实的场景中,我需要处理对象中嵌套的对象。我为了确定而尝试了一下,但处理嵌套的花括号和可能的字符集很快就变得非常困难。通常我很喜欢使用正则表达式,但在这种情况下,我希望有更简单的解决方案。 - Ubiquitous Che
事实证明,从技术上讲,它们仍然发送有效的Json。请参见我在上面给Matthew的第二条评论。这对我来说很烦人,但现在我可以处理它了。 - Ubiquitous Che
2
不,这确实不是正确的JSON。您误解了规范,它是“基于JavaScript编程语言的子集,标准ECMA-262 3rd Edition - December 1999”。没有JavaScript解析器会保留与多个重复键相关联的值之外的任何值。请告诉JSON发明人Douglas Crockford,他错了。 - Joel Mueller
@Joel:错了。至少有两个解析器。一个是我写的,另一个是Newtonsoft提供的。仅仅因为许多解析器和你一样做出了同样错误的假设,并不意味着他们是正确的。他们正确地实现了规范。你不必喜欢它,但坚持认为遵循“规范”的东西是错误的就是愚蠢的。当在JSON对象中运行“执行”JS时得到的结果与JSON结构的正确性问题无关,特别是如果JSON结构不打算作为JS执行,而只是数据传输。完。 - Deltics
我正在正确解释规范 - 是你错误地解释了它。规范说明名称应该是唯一的。如果它要求名称必须是唯一的,那么它会明确指出必须唯一。规范清楚而有意使用“应该”,而不是“必须”,并引用了定义这些术语的RFC 2119。把“应该”解读为“必须”的解释是不正确的。事实如此。 - Deltics
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接