Отдельные элементы Python устанавливаются в JSON

У меня есть несколько переменных, которые я хочу преобразовать в строку объекта JSON. Некоторые из этих переменных являются множествами. Но я не могу заставить это работать, если в наборах есть только одна запись.

Я уже рассматривал следующий вопрос, но я работаю не с литералами, а с переменными. Так что мне это действительно не помогло. Как передать список, содержащий одну строку в Python?

Я пробовал следующий класс для кодирования данных:

class SetEncoder(json.JSONEncoder):
  def default(self, obj):
    if isinstance(obj, set):
      setLen = len(obj)
      if len(obj) != 1:
        setAsList = list(obj)
      else:
        setAsList = [obj]
      logging.debug("DIAG: IN SetEncoder with obj = %r ; setAsList = %r ; setLen = %s" % (obj, setAsList, setLen))
      return setAsList
    return json.JSONEncoder.default(self, obj)

И вот мой код, чтобы попытаться закодировать Set:

  # following is just to demonstrate the problem; no matter how I try to
  # set the single element set, the code to process it doesn't work;
  # I've tried set(("CAT1")), set(("CAT1",)), set(["CAT1",])
  countriesSet = set(["US", "DE"])
  categoriesSet = set(["CAT1"])

  body = {
    "ownerId": OWNER_ID,
    "countries": countriesSet,
    "categories": categoriesSet
  }
  bodyJson = json.dumps(body, cls=SetEncoder)

И вот мой результат:

DEBUG:root:DIAGDIAGDIAG: countriesSet = {'US', 'DE'}, len = 2; categoriesSet = {'CAT1'}, len = 1
DEBUG:root:DIAG: IN SetEncoder with obj = {'US', 'DE'} ; setAsList = ['US', 'DE'] ; setLen = 2
DEBUG:root:DIAG: IN SetEncoder with obj = {'CAT1'} ; setAsList = [{'CAT1'}] ; setLen = 1
ERROR:root:parseXML: Encountered exception - Circular reference detected for destination <Element 'destination' at 0x000002570535B728>

Как видите, эта единственная запись обведена фигурными скобками, а рабочие записи - нет.

У кого-нибудь есть идеи?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
242
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Что не так с просто:

class SetEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, set):
            return list(obj)
        return json.JSONEncoder.default(self, obj)

По [x] вы оберточная бумага ваш установленный объект в списке, а не "конвертируете" его. (Это разворачивание этой упаковки вызывает циклическую ссылку)

Re: обсуждение

Просто чтобы нам было понятно, это то, что я предлагаю. Я ни в коем случае не теряю скобки вокруг одного элемента (список / кортеж / набор): импортировать json

class SetEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, set):
            return list(obj)
        return json.JSONEncoder.default(self, obj)


objs = {
    'one_element_list_int': [1],
    'one_element_list_tup': ("foo",),
    'one_element_list_set': {10},
    'two_element_list_int': [2, 3],
    'two_element_list_tup': ("bar", "baz"),
    'two_element_list_set': {11,12},
}

for (k,v) in objs.items():
    dump = json.dumps(v, cls=SetEncoder)
    print(k+": ", v, "->", dump)

Производит

one_element_list_int:  [1] -> [1]
one_element_list_tup:  ('foo',) -> ["foo"]
one_element_list_set:  {10} -> [10]
two_element_list_int:  [2, 3] -> [2, 3]
two_element_list_tup:  ('bar', 'baz') -> ["bar", "baz"]
two_element_list_set:  {11, 12} -> [11, 12]

Проблема в том, что JSON.dumps () в конечном итоге "теряет" набор: "категории": "CAT1", "страны": ["DE", "США"]

Westy 27.10.2018 01:29

@ Вести набор не то, что понимает json. Вам нужно будет преобразовать его во что-то еще, чтобы получить правильный JSON (в этом случае вы используете список, но вы также можете сериализовать его в строку и т. д.). Затем вы можете реализовать собственный декодер JSON для создания Python set из сериализованного / любого / правильного JSON.

jedwards 27.10.2018 01:41

Верно, я знаю, что JSON не знает, что такое Set. Но он может справиться со списком. Я не понимаю, как не «потерять» список, когда он всего один. Тот факт, что одна запись не заключена в квадратные скобки, убивает мою службу, которую мы вызываем с данными. Что я могу сделать, чтобы их сохранить, независимо от количества записей?

Westy 27.10.2018 02:06

@Westy, как я показал, используйте Толькоlist(obj), когда isinstance(obj, set). Другими словами, перестаньте заботиться о длине набора. Вы пробовали код, который я опубликовал?

jedwards 27.10.2018 03:29

Да, я уже попробовал опубликованный вами код и вернулся к нему. Вот что я получаю, когда превращаю его в список: «страны»: [«США», «Германия»], «категории»: «CAT1» Все, что мне нужно, - это правильно отформатировать список, когда есть только одна запись в список. Это не похоже на то, что это должно быть так сложно, но я потратил на это так много времени и до сих пор не могу заставить его работать.

Westy 29.10.2018 18:08

@Westy Взгляните на изменение вопроса, и, если у вас все еще есть проблемы, подумайте об обновлении вопроса с помощью кода / создании нового.

jedwards 29.10.2018 18:19

На самом деле, чем больше я смотрю на это, тем больше кажется, что проблема в библиотеке requests Python. Из сообщений журнала в программе Python я вижу следующее: «страны»: [«США», «Германия»], «категории»: [«CAT1»] И в моем микросервисе Node.js, когда я получаю запрос, я вижу: "страны": ["США", "Германия"], "категории": "CAT1"

Westy 29.10.2018 18:22

Спасибо, jedwards. Вы помогли мне сузить круг вопросов. Я создам новый вопрос.

Westy 29.10.2018 18:39

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