Skip to content

Instantly share code, notes, and snippets.

@imZack
Forked from reegnz/README.md
Created March 30, 2021 02:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imZack/5c0960424d2ce54c4dd6bf6a0276a4d3 to your computer and use it in GitHub Desktop.
Save imZack/5c0960424d2ce54c4dd6bf6a0276a4d3 to your computer and use it in GitHub Desktop.
CamelCase <--> snake_case conversion in jq

CamelCase <--> snake_case conversion with jq

tl;dr

I provide you with 3 jq lib functions that will help you in converting between snake_case and CamelCase.

The interface

I want to change keys in my json from camelcase to snake_case.

{
  "SomeKey": {
    "NestedKey": "NestedValue",
    "NestedList": [
      {
        "NestedKey": "NestedValue"
      },
      {
        "NestedKey": "NestedValue"
      },
      {
        "NestedKey": "NestedValue"
      }
    ]
  }
}

It would be nice to do this with a simple command, something like this:

<my.json | jq 'map_keys(camel_to_snake)' > my_snake.json

This would result in the following output:

{
  "some_key": {
    "nested_key": "NestedValue",
    "nested_list": [
      {
        "nested_key": "NestedValue"
      },
      {
        "nested_key": "NestedValue"
      },
      {
        "nested_key": "NestedValue"
      }
    ]
  }
}

We also expect that we get the same CamelCase json back if we convert back the snake_case version.

diff <(<my.json jq) <(<my.json | jq 'map_keys(camel_to_snake)|map_keys(snake_to_camel)'); echo $?
0

The solution

Once you put the following functions into $HOME/.jq file the above command will just work!

def map_keys(mapper):
  walk(
    if type == "object"
    then
      with_entries({
        key: (.key|mapper),
	value
      })
    else .
    end
  );

def camel_to_snake:
  [
    splits("(?=[A-Z])")
  ]
  |map(
    select(. != "")
    | ascii_downcase
  )
  | join("_");

def snake_to_camel:
  split("_")
  | map(
    split("")
    | .[0] |= ascii_upcase
    | join("")
  )
  | join("");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment