2015-06-15 3 views
9

Отказ от ответственности: Я проверил вопрос here, и он не отвечает мне.Elixir - Вложенный анализ JSON для структур

Я пытаюсь придумать способ вложенного анализа синтаксиса JSON. Пример:

{"name": "blah blah", "address": {"street": "smthing"}} 

Я хочу, чтобы достичь этого результата:

%User{name: "blah blah", address: %Address{street: "smthing"}} 

Потому что тогда было бы легче подключить проверку (с использованием Vex для exapmle).

Я знаю, что Poison поддерживает опцию «as struct», но не обеспечивает вложенность. Выше будет обработан:

%User{name: "blah blah", address: %{"street" => "smthing"}}. 

Я знаю, что я мог бы написать реализацию декодера для модуля User, но я предполагаю, что это не предназначен случай использования, и это не будет универсальным.

Когда вы задавались вопросом о реализации, я не мог найти способ узнать, является ли атом модулем ... может быть, мне нужно пойти с :code.is_loaded(module_name)?

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

ответ

9

Я считаю, что выше теперь можно с ядом:

defmodule User do 
    @derive [Poison.Encoder] 
    defstruct [:address] 
end 

defmodule Address do 
    @derive [Poison.Encoder] 
    defstruct [:street] 
end 

Poison.decode(response, as: %User{address: %Address{}}) 
+1

Это отлично работает для меня с Poison 2.0. Благодаря @Maikon – q231950

5

В настоящее время единственным вариантом, о котором я знаю, является предоставление вашей собственной реализации для протокола Poison.Decoder (обратите внимание на завершающий r) протокол. Это имеет дополнительное преимущество, что вы можете иметь эти преобразования в одном месте и просто нужно написать as: User, чтобы правильно преобразовать адрес. Например:

defimpl Poison.Decoder, for: User do 
    def decode(task_list, options) do 
    Map.update! task_list, :address, fn address -> 
     Poison.Decode.decode(address, Keyword.merge(options, as: [Address])) 
    end 
    end 
end 

Следует отметить, что внутренний вызов decode не от Poison.Decoder, но Poison.Decode, без задней r в имени модуля. Вы не получите ошибку, если используете неправильный, это просто не сработает, что может быть больно отлаживать.

В конечном счете, я думаю, что в Poison нужно сделать немного работы, чтобы сделать все это более интересным в использовании. Может быть, макрос, который упростит реализацию Poison.Decoder реализаций для настраиваемых структур. Возможно, также поддерживает вложенные параметры структуры, такие как as: %User{address: Address}, которые не должны быть слишком сложными для реализации. Также я думаю, что имена модулей Decode и Decoder слишком сбиты с толку, и один из них должен быть переименован. Если у меня будет время, возможно, я сделаю эти предложения и настрою пиар с Poison.

+0

Если я идти по этому пути, может быть, более общий подход заключается в реализации универсального декодера, который я бы 'использовать BaseDecoder', а затем в' Защита __using __ (_), do: etc', чтобы определить реализацию для протокола. Но тогда я должен был бы знать, является ли атом допустимым модулем, который является структурой. – Olinasc

+0

Я лично считаю, что это слишком много магии, но эй, почему бы и нет ;-) Конечно, эта настройка может быть упрощена, но я бы предпочел более явный подход. Я открыл для него проблему Github, давайте посмотрим, что думает автор оригинала, а потом, возможно, я попытаюсь ее реализовать. https://github.com/devinus/poison/issues/35 –

Смежные вопросы