Skip to content

Instantly share code, notes, and snippets.

@akoutmos
Created January 30, 2022 04:15
Show Gist options
  • Save akoutmos/f14e0f719b4efbee2526858b34869004 to your computer and use it in GitHub Desktop.
Save akoutmos/f14e0f719b4efbee2526858b34869004 to your computer and use it in GitHub Desktop.
Pretty print JSON passed via STDIN using Elixir shell script
#! /usr/bin/env elixir
# Install required deps
Mix.install([:jason])
# The pretty printing module
defmodule JsonPrettyPrinter do
def get_stdin_data do
# Fetch data from STDIN and decode JSON
:stdio
|> IO.read(:all)
|> Jason.decode()
|> case do
{:ok, json_data} -> json_data
_ -> raise "Invalid JSON payload was provided"
end
end
def pretty_print_json(data) do
body =
data
|> Enum.to_list()
|> Enum.sort()
|> Enum.map(fn {key, value} ->
~s/ #{color_data(:green, key)}#{color_data(:yellow, ":")} #{pretty_print(value, 1)}/
end)
|> Enum.join(",\n")
"""
#{color_data(:yellow, "{")}
#{body}
#{color_data(:yellow, "}")}
"""
end
def pretty_print(current_data, _indent_level) when is_number(current_data) do
color_data(:blue, current_data)
end
def pretty_print(current_data, _indent_level) when is_boolean(current_data) do
color_data(:magenta, current_data)
end
def pretty_print(current_data, _indent_level) when is_binary(current_data) do
color_data(:cyan, ~s/"#{current_data}"/)
end
def pretty_print(current_data, _indent_level) when is_nil(current_data) do
color_data(:red, "null")
end
def pretty_print(current_data, _indent_level) when current_data == %{} do
color_data(:yellow, "{}")
end
def pretty_print(current_data, _indent_level) when current_data == [] do
color_data(:yellow, "[]")
end
def pretty_print(current_data, indent_level) when is_list(current_data) do
indent_padding = String.duplicate(" ", indent_level * 2)
next_indent_padding = String.duplicate(" ", (indent_level + 1) * 2)
body =
current_data
|> Enum.sort()
|> Enum.map(fn element ->
~s/#{next_indent_padding}#{pretty_print(element, indent_level + 1)}/
end)
|> Enum.join(",\n")
Enum.join(
[
color_data(:yellow, "["),
body,
"#{indent_padding}#{color_data(:yellow, "]")}"
],
"\n"
)
end
def pretty_print(current_data, indent_level) when is_map(current_data) do
indent_padding = String.duplicate(" ", indent_level * 2)
next_indent_padding = String.duplicate(" ", (indent_level + 1) * 2)
body =
current_data
|> Enum.to_list()
|> Enum.sort()
|> Enum.map(fn {key, value} ->
~s/#{next_indent_padding}#{color_data(:green, key)}#{color_data(:yellow, ":")} #{pretty_print(value, indent_level + 1)}/
end)
|> Enum.join(",\n")
Enum.join(
[
color_data(:yellow, "{"),
body,
"#{indent_padding}#{color_data(:yellow, "}")}"
],
"\n"
)
end
defp color_data(:red, data), do: IO.ANSI.red() <> "#{data}" <> IO.ANSI.reset()
defp color_data(:blue, data), do: IO.ANSI.blue() <> "#{data}" <> IO.ANSI.reset()
defp color_data(:cyan, data), do: IO.ANSI.cyan() <> "#{data}" <> IO.ANSI.reset()
defp color_data(:magenta, data), do: IO.ANSI.magenta() <> "#{data}" <> IO.ANSI.reset()
defp color_data(:green, data), do: IO.ANSI.green() <> "#{data}" <> IO.ANSI.reset()
defp color_data(:yellow, data), do: IO.ANSI.yellow() <> "#{data}" <> IO.ANSI.reset()
defp color_data(:white, data), do: IO.ANSI.white() <> "#{data}" <> IO.ANSI.reset()
end
# Perform the pretty printing
JsonPrettyPrinter.get_stdin_data()
|> JsonPrettyPrinter.pretty_print_json()
|> IO.puts()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment