Skip to content

Instantly share code, notes, and snippets.

@reegnz
Created June 19, 2020 10:39
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save reegnz/5bceb53427008a4ff9367eb8eae97b85 to your computer and use it in GitHub Desktop.
Save reegnz/5bceb53427008a4ff9367eb8eae97b85 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("");
@lehainam-dev
Copy link

Thank you so much. You just save someone's day.

@reegnz
Copy link
Author

reegnz commented Apr 17, 2022

@lehainam-dev you're welcome! :)

@huyngogia1997
Copy link

Thank you so much. It is exactly what I needed.

@wandersonwhcr
Copy link

wtf? can I add custom functions to jq? AWESOME! THANK YOU!

@denisborovikov
Copy link

Google brought me here. You rock! Thank you!

@qiangli
Copy link

qiangli commented Oct 17, 2022

Thanks! You rock!

@reegnz
Copy link
Author

reegnz commented Oct 20, 2022

In case people are interested, I have made other jq functions as well, for converting from/to camel, snake, kebab, dotted, etc. cases as well: https://github.com/reegnz/dotfiles/tree/master/jq

@opsb
Copy link

opsb commented Feb 25, 2024

Case changing and a great pattern for adding utility functions to jq, thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment