Skip to content

Instantly share code, notes, and snippets.

@xhh
Last active May 25, 2021 03:48
Show Gist options
  • Save xhh/089e2b84ccd9a5d1831d0590639faa4c to your computer and use it in GitHub Desktop.
Save xhh/089e2b84ccd9a5d1831d0590639faa4c to your computer and use it in GitHub Desktop.

JSON 递归处理

数据

json = """
[
  {
    "k1": "v1",
    "k2": {
      "k21": "v21",
      "k22": "v22"
    }
  },
  {
    "k4": "v4",
    "k5": "v5",
    "k6": "v6"
  }
]
"""

_expected_result = """
[
  {
    "k1": "k1",
    "k2": {
      "k21": "k2.k21",
      "k22": "k2.k22"
    }
  },
  {
    "k4": "k4",
    "k5": "k5",
    "k6": "k6"
  }
]
"""

依赖

Mix.install([:jason])

实现

defmodule Solution do
  def run(json_str, encode_opts \\ []) do
    with {:ok, data} <- Jason.decode(json_str) do
      data
      |> process()
      |> Jason.encode(encode_opts)
    end
  end

  def run!(json_str, encode_opts \\ []) do
    json_str
    |> Jason.decode!()
    |> process()
    |> Jason.encode!(encode_opts)
  end

  def process(data), do: process_item(data, "")

  # 处理数组
  defp process_item(data, value_prefix) when is_list(data) do
    Enum.map(data, &process_item(&1, value_prefix))
  end

  # 处理对象
  defp process_item(%{} = data, value_prefix) do
    Map.new(data, fn {k, v} -> {k, process_item(v, build_value_prefix(value_prefix, k))} end)
  end

  # 处理值
  defp process_item(_data, value_prefix), do: value_prefix

  defp build_value_prefix("", current_key), do: current_key
  defp build_value_prefix(previous_prefix, current_key), do: previous_prefix <> "." <> current_key
end
Solution.run!(json, pretty: true)
|> IO.puts()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment