JsonConvert.DeserializeObject <dynamic>() добавляет дополнительный набор фигурных скобок - PullRequest
0 голосов
/ 05 мая 2020

Я тестировал динамическую обработку json на моем бэкэнде без использования объектов (так как я не знаю структуру объектов, и создание их для тысяч соединений, которые это будет делать, - пустая трата времени) ). Я хочу иметь возможность программировать интерфейс без необходимости настраивать код для каждого отдельного интерфейса, к которому я буду подключаться, и передавать данные в руки технических специалистов, но не программистов вроде меня.

Играя с NewtonSoft. Json Я пришел к выводу, что есть некоторые странности, которые я не совсем понимаю, и я не одинок, поскольку я видел, как многие люди писали похожие вопросы без каких-либо разрешение или понимание того, что происходит.

Здесь я нашел множество вопросов, в которых DeserializeObject упоминается как возвращающий JObject с дополнительным набором фигурных скобок.

Пример:

Строка «data» содержит следующее:

{\r\n  \"firstName\": \"John\",\r\n  \"lastName\": \"Doe\",\r\n  \"IDNum\": 123456,\r\n  \"phoneNumbers\": [\r\n    {\r\n      \"number\": \"6123334444\"\r\n    },\r\n    {\r\n      \"number\": \"7635556666\"\r\n    }\r\n  ]\r\n}

JObject rest = JsonConvert.DeserializeObject<dynamic>(data.ToString()); 

Но JObject «rest» добавляет к нему дополнительный набор фигурных скобок:

{{
    "firstName": "John",
    "lastName": "Doe",
    "IDNum": 123456,
    "phoneNumbers": [
    {
       "number": "6123334444"
    },
    {
      "number": "7635556666"
    }
  ]
}}

Делает эту команду JArray неработоспособной:

JArray obj = JArray.Parse(rest ) as JArray;

В одном из постов здесь говорилось о преобразовании его обратно в строку и простой замене фигурных скобок следующим образом:

string cleanRest = rest.ToString().Replace("{{", "{").Replace("}}", "}");

Что заканчивается строкой "cleanRest" ":

{\r\n  \"firstName\": \"John\",\r\n  \"lastName\": \"Doe\",\r\n  \"IDNum\": 123456,\r\n  \"phoneNumbers\": null\r\n}

Конечно cleanRest не является допустимым json, и эта строка выдает ошибку:« Newtonsoft. Json .JsonReaderException: 'Ошибка чтения JArray из JsonReader. Текущий JsonReade Элемент r не является массивом: StartObject. Путь '', строка 1, позиция 1. '"при запуске следующей строки:

JArray obj = JArray.Parse(cleanRest) as JArray;

Сначала у меня возникли проблемы с ответом, включая xmlns: http://schemas.microsoft.com/2003/10/Serialization, и мне пришлось откройте его как XmlDocument и преобразуйте следующим образом:

    private string returnJson(string response)
    {
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(response);
        return doc.DocumentElement.FirstChild.InnerText;
    }

Но вся эта болтовня заставляет меня думать, что я не справляюсь с этим правильно, хотя я прочитал пару блогов, которые касались реализации MS of json имеет такие странные причуды. Но мне не нужно исправлять ответ; это просто заставляет меня нервничать из-за будущих проблем с этим.

Кто-нибудь знает, что происходит, и как это решить ?

1 Ответ

1 голос
/ 05 мая 2020

Итак, разбор строки JSON не дает вам другой строки, которую вы можете проанализировать. Он создает объект. Его нужно снова сериализовать. Работает корректно.

Однако объект, представленный строкой, не является массивом. Это приведет к ошибке, если вы сериализуете его и передадите JArray.parse, потому что это не массив.

Фактически вы можете сериализовать rest с помощью ToString, но просто передав rest в JArray.parse выиграл 't компилируется, так что не понимайте, что вы действительно делаете.

Вот какой-то код, который работает

public static void Main()
{
    var json = "{\r\n  \"firstName\": \"John\",\r\n  \"lastName\": \"Doe\",\r\n  \"IDNum\": 123456,\r\n  \"phoneNumbers\": [\r\n    {\r\n      \"number\": \"6123334444\"\r\n    },\r\n    {\r\n      \"number\": \"7635556666\"\r\n    }\r\n  ]\r\n}";

    JObject rest = JsonConvert.DeserializeObject<dynamic>(json); 

    Console.WriteLine(rest.ToString());

    // this works, since phoneNumbers is an array
    JArray obj = JArray.Parse(rest["phoneNumbers"].ToString()) as JArray;       

    // this fails because an object is not an array
    obj = JArray.Parse(rest.ToString()) as JArray;      
}

Если вы хотите получить доступ к свойствам, вы можете использовать синтаксис массива, если знаете имя, ie. rest["phoneNumbers"]. Или, если вы не знаете, какие у него свойства, вы можете сделать это:

foreach (var x in rest)
{
    string name = x.Key;
    JToken value = x.Value;
}

Вы также можете изменить значения:

rest["firstName"] = "My New Name";

или добавить новые

rest["newproperty"] = 2500;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...