Created
March 21, 2018 12:04
-
-
Save remi6397/836730facb9c4206cdb507a136909dbf to your computer and use it in GitHub Desktop.
Several parts of XML <-> JSON converter (taken from my Phoenix webapp)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule PastebinderWeb.JSONToXmlHelper do | |
def to_xml(map) do | |
list = to_list(map) | |
:xmerl.export_simple(list, :xmerl_xml) | |
|> List.flatten | |
|> to_string | |
end | |
defp to_list(map) when is_map(map) do | |
keyword = Map.to_list(map) | |
Enum.map(keyword, fn({k, v}) -> {k, [], to_list(v)} end) | |
end | |
defp to_list(list) when is_list(list), do: Enum.map(list, fn(x) -> {:item, [], to_list(x)} end) | |
defp to_list(some), do: [to_charlist some] | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule PastebinderWeb.MapToKeywordHelper do | |
def convert(map) when is_map(map) do | |
keyword = Map.to_list(map) | |
Enum.map keyword, fn({k, v}) -> {k, convert(v)} end | |
end | |
def convert(list) when is_list(list), do: Enum.map(list, &convert/1) | |
def convert(some), do: some | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule PastebinderWeb.PasteView do | |
use PastebinderWeb, :view | |
alias PastebinderWeb.PasteView | |
def render("index.json", %{pastes: pastes}) do | |
%{data: render_many(pastes, PasteView, "paste.json")} | |
end | |
def render("show.json", %{paste: paste}) do | |
%{data: render_one(paste, PasteView, "paste.json")} | |
end | |
def render("paste.json", %{paste: paste}) do | |
%{id: paste.id, | |
title: paste.title, | |
content: paste.content, | |
visibility: paste.visibility, | |
author: render_one(Pastebinder.Accounts.get_user!(paste.author_id), PastebinderWeb.UserView, "user.json")} | |
end | |
def render(resource, opts) do | |
if String.ends_with?(resource, ".xml") do | |
render(List.last(Regex.run(~r/^(.*)\.xml$/, resource)) <> ".json", opts) | |
|> PastebinderWeb.JSONToXmlHelper.to_xml | |
else | |
raise FunctionClauseError | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Plug.Parsers.XML do | |
@behaviour Plug.Parsers | |
import Plug.Conn | |
def init(opts) do | |
opts | |
end | |
def parse(conn, _, "xml", _headers, opts) do | |
decoder = Keyword.get(opts, :xml_decoder) || raise ArgumentError, "XML parser expects a :xml_decoder option" | |
conn | |
|> read_body(opts) | |
|> decode(decoder) | |
end | |
def parse(conn, _type, _subtype, _headers, _opts) do | |
{:next, conn} | |
end | |
defp decode({:ok, body, conn}, decoder) do | |
case decoder.string(String.to_charlist(body)) do | |
{parsed, []} -> | |
{:ok, to_map([to_json(parsed)]), conn} | |
_error -> | |
raise "Malformed XML" | |
end | |
end | |
defp to_map(keyword) do | |
case keyword do | |
[{k, v}] -> | |
%{to_string(k) => to_map(v)} | |
[{k, v} | tl] -> | |
Map.put to_map(tl), to_string(k), to_map(v) | |
list when is_list(list) -> | |
Enum.map list, &to_map/1 | |
el -> el | |
end | |
end | |
defp to_json([{:xmlElement, :item, :item, _, _ns, _, _, _attrs, contents, _, _, _}]) do | |
[to_json(contents)] | |
end | |
defp to_json([{:xmlElement, :item, :item, _, _ns, _, _, _attrs, contents, _, _, _} | tl]) do | |
[to_json(contents) | to_json(tl)] | |
end | |
defp to_json([{:xmlElement, tag, tag, _, _ns, _, _, _attrs, contents, _, _, _}]) do | |
[{tag, to_json(contents)}] | |
end | |
defp to_json([{:xmlElement, tag, tag, _, _ns, _, _, _attrs, contents, _, _, _} | tl]) do | |
[{tag, to_json(contents)} | to_json(tl)] | |
end | |
defp to_json([{:xmlText, _, _, _, text, :text}]) do | |
to_json(text) | |
end | |
defp to_json({:xmlElement, tag, tag, _, _ns, _, _, _attrs, contents, _, _, _}) do | |
{tag, to_json(contents)} | |
end | |
defp to_json('nil'), do: nil | |
defp to_json('true'), do: true | |
defp to_json('false'), do: false | |
defp to_json(t) do | |
IO.write "-- Parsing --\n" | |
IO.inspect t | |
try do | |
try do | |
String.to_integer(to_string(t)) | |
rescue | |
_ -> String.to_float(to_string(t)) | |
end | |
rescue | |
_ -> to_string t | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment