Json.NET (Newtonsoft.Json) - два «свойства» с одинаковым именем? - PullRequest
4 голосов
/ 07 октября 2010

Я пишу на C # для .NET Framework 3.5.

Я пытаюсь проанализировать Json для объекта JO.

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» как свойство, и это свойство перезаписывается.

Я получаю этот Json от службы, которая закодирована в Delphi. Я пытаюсь создать C # прокси для этого сервиса. С точки зрения Delphi, «TBox» понимается как тип возвращаемого объекта. Внутренние свойства («Имя», «Длина», «Ширина», «Высота») понимаются как обычные свойства.

Я могу сериализовать и десериализовать пользовательский объект 'TBox', который имеет свойства Name, Length, Width и Height. Это нормально.

Что я хочу сделать, так это пройти по всем разделам TBox таким образом, чтобы извлечь следующие три строки Json.

Во-первых:

{
    "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 голосов
/ 07 октября 2010
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
        }
    }
]
3 голосов
/ 07 октября 2010

Если я не ошибаюсь, правильный ответ на этот вопрос заключается в том, что вы на самом деле не JSON.Так что нет, заставить анализатор JSON анализировать его, вероятно, не получится.

Возможно, у вас нет никакого контроля над источником ввода, поэтому я бы использовал Regex или что-то для-фильтровать строку.Преврати его в нечто вроде:

{"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 
        }
    ]
}

И относись к нему как к массиву, который он есть.

...