I'm working with the woocommerce API to retrieve and store information. Currently our setup is designed to use camel case instead of underscores. I'm using jq
to process our information, but I'm curious how I can use the sub(regex, tostring)
function to replace the underscores in my JSON with camelCase?
Here's an example of the code
"line_items": [
{
"id": xxxx,
"name": "xxxx",
"sku": "xxxx",
"product_id": xxxx,
}
For example, according to another answer on SO that I found, this works: curl https://www.testsite.com/wp-json/wc/v1/orders -u user:pass | jq '.[] | with_entries( if .key | contains("_") then .key |= sub("_";"") else . end)'
and remove the underscores.
The result is:
"lineitems": [
{
"id": xxxx,
"name": "xxxx",
"sku": "xxxx",
"productid": xxxx,
}
However, when I try curl https://www.testsite.com/wp-json/wc/v1/orders -u user:pass | jq '.[] | with_entries( if .key | contains("_") then .key |= sub("(\\_)([a-z])";"$2\u") else . end)'
I don't get the results I would expect.
The expected results would be:
"lineItems": [
{
"id": xxxx,
"name": "xxxx",
"sku": "xxxx",
"productId": xxxx,
}
I don't have a lot of experience using jq
so I'm not sure what I'm doing wrong. Is there a better solution to this problem?
Here's a jq function that will convert "a_bcd_ef" to "aBcdEf", which seems to be what you want:
def camel:
gsub( "_(?<a>[a-z])"; .a|ascii_upcase);
Example usage:
"a_bcd_ef" | camel
If you want a simple one-liner to process JSON strings from STDIN:
$ jq 'gsub( "_(?<a>[a-z])"; .a|ascii_upcase)'
If you only want the first occurrence of "_[a-z]" converted, then of course you'd use sub
. And so on.
To apply this function to ALL keys in an object, you could write:
with_entries( .key |= camel )
To change ALL keys in ALL objects within a JSON entity, you could use walk/1
:
walk(if type == "object" then with_entries(.key |= camel) else . end)
If your jq does not have walk/1
then you can simply include its definition (easily found by googling), either before it is invoked, or perhaps in your ~/.jq file.
Although not as concise as the gsub solution of @peak, this one is easier on the eye and easier for beginners to understand IMHO.
You can put this into a script called 'snake_to_camel.jq' and chmod +x snake_to_camel.jq
#!/usr/bin/env jq -f
def head:
.[0:1];
def tail:
.[1:];
def capitalize:
(head | ascii_upcase) + tail;
def snake_to_camel:
split("_") |
head + (tail | map(capitalize)) |
join("");
def map_keys(mapper):
walk(if type == "object" then with_entries(.key |= mapper) else . end);
map_keys(snake_to_camel)
Example usage:
curl https://example.com/input.json | ./snake_to_camel.jq
Some of the jq features I've used here:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With