Как десериализовать JSON в IList<KeyValuePair<string, object>> с пробелами в ключе?

У меня большая проблема с десериализацией моего JSON в объект. Его нужно десериализовать, чтобы IList<KeyValuePair<string, object>> проблема в том, что в ключах есть пробелы.

"spec": {
         "SOMETHING WITH SPACES" : "10"
         etc. 
         ...
}
public class SomeObject
{
...
public IList<KeyValuePair<string, object>> spec{ get; set; }
...
}

Код десериализации:

var sr = new ServiceStack.Text.JsonSerializer<SomeObject>();
var esResult = sr.DeserializeFromString(responseJson);

responseJson — это GET от ElasticSearch.

То, что я получаю в своем поле, равно нулю. Если у меня есть ключ без пробелов, он нормально десериализуется, и я получаю свой IList<KeyValuePair<string, object>>

опубликовать весь json

Kunal Mukherjee 29.05.2019 11:31

Почему бы просто не использовать Dictionary<string, object> вместо IList<KeyValuePair<string, object>>?

dbc 29.05.2019 11:32

Обычно интерфейсы вызывают проблемы при сериализации. Вероятно, у сериализатора нет возможности узнать, где взять реализацию IList, которая у вас есть. Если сериализатор добавляет больше информации о w.r.t. реализация в сериализованном представлении может быть использована для десериализации, но это то, что обычно не происходит в мире JSON. Попробуйте изменить это только на List, а не на IList.

Eben Roux 29.05.2019 11:39

Я не могу использовать Dictionary, потому что этот объект используется в нескольких местах, таких как List<KVP>. Изменение IList на List не работает, но спасибо за предложение.

Skundlony 29.05.2019 11:48

Пожалуйста, смотрите мой ответ о том, как анализировать с помощью словаря и по-прежнему получать нужный вам список.

Peter B 29.05.2019 12:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
1 290
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я предполагаю, что ваш сериализатор JSON создает некоторые проблемы. Я бы рекомендовал использовать Newtonsoft.Json (в NuGet) Я пробовал следующий код, и он отлично работает:

        var o1 = new SomeObject() { spec = new List<KeyValuePair<string, object>>() };
        o1.spec.Add(new KeyValuePair<string, object>("test with spaces", 10));

        var r1 = Newtonsoft.Json.JsonConvert.SerializeObject(o1);
        Console.WriteLine(r1);
        var o2 = Newtonsoft.Json.JsonConvert.DeserializeObject<SomeObject>(r1);
        var r2 = Newtonsoft.Json.JsonConvert.SerializeObject(o2);
        Console.WriteLine(r2);

Результат

{"spec":[{"Key":"test with spaces","Value":10}]}
{"spec":[{"Key":"test with spaces","Value":10}]}

Нулевых значений нет, все работает нормально.

Обновлено: я на самом деле не вижу причин, почему пробелы вообще должны быть проблемой. Они просто часть строки.

Обратите внимание, что JSON, который вы создаете, а затем анализируете, содержит [ ], тогда как OP не имеет [ ] в своем JSON.

Peter B 29.05.2019 11:45

Newtonsoft.Json сохраняет выходные данные со словами Key и Value. У меня есть много индексов в elasticsearch, сохраненных с помощью ServiceStack json, и они выглядят немного иначе.

Skundlony 29.05.2019 11:46

Вы правы, это совсем другое. Я бы порекомендовал, как Кунал Мукерджи, опубликовать полный пример json-файла, чтобы лучше понять, как он отформатирован.

Malior 29.05.2019 12:52

Если вы не возражаете против использования Newtonsoft.Json:

    const string json = @"{""spec"": { ""SOMETHING WITH SPACES"" : ""10"", ""SOMETHING WITH MORE SPACES"" : ""20"" }}";
    dynamic data = JsonConvert.DeserializeObject(json);
    Dictionary<string, string> list = data["spec"].ToObject<Dictionary<string, string>>();
    foreach (var item in list)
    {
        Console.WriteLine(item.Key + ", " + item.Value);
    }
Ответ принят как подходящий

Здесь нельзя использовать IList или List, потому что в исходном JSON нет [ ], что является обязательным условием, если вы хотите разобрать такую ​​коллекцию. Другими словами, без [ ] вы не сможете разобрать коллекцию, по крайней мере, не пройдя через множество обручей.

Вместо этого вам нужно использовать словарь, как уже было предложено в комментариях.

Примечание. Я использовал Newtonsoft JsonConvert, потому что вы не указали, какой у вас синтаксический анализатор, но это не должно иметь большого значения для моих аргументов.

Рабочий код:

var json = "{ \"spec\": { \"SOMETHING WITH SPACES\" : \"10\" } }";
var someObj = JsonConvert.DeserializeObject<SomeObject>(json);

public class SomeObject
{
    public Dictionary<string, object> spec{ get; set; }
}

После этого вы можете привести свойство spec к IEnumerable и перебрать все, что было найдено:

foreach (var pair in someObj.spec as IEnumerable<KeyValuePair<string, object>>)
{
    Console.WriteLine(pair.Key + " -> " + pair.Value);
}

Или даже преобразовать его в список:

var list = someObj.spec.ToList();
foreach (var pair in list)
{
    Console.WriteLine(pair.Key + " -> " + pair.Value);
}

Скрипт .NET: https://dotnetfiddle.net/15l2R3

Я должен использовать List<KeyValuePair<string, object>>, потому что в моей спецификации могут быть ключи с одинаковыми именами.

Skundlony 29.05.2019 13:59

В этом случае см. эта страница о наличии JSON с повторяющимися ключами. В нем говорится: «(Синтаксический анализатор может выбрать) вернуть все пары ключ-значение или даже отклонить JSON с ошибкой синтаксического анализа, и все эти варианты поведения будут действительными. Тем не менее, большинство популярных реализаций... следуют правило взятия только последней пары ключ-значение». Я не знаю каких-либо парсеров, которые справляются с этим, сохраняя все дубликаты, и вам может быть трудно найти его.

Peter B 29.05.2019 15:52

Другие вопросы по теме