Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQ convert to number, convert to boolean when generating new json from shell variables

Tags:

json

jq

I'm attempting to generate json output where the input is coming from shell variables.

happystring="Bob Ross"
unhappynumber1="1942"
unhappyboolean=true

JSON=$(jq -n \
        --arg happystring "$happystring" --arg unhappynumber1 "$unhappynumber1" \
        --arg unhappyboolean $unhappyboolean \
        '
        {
            happystring: $happystring,
            unhappynumber1: $unhappynumber1,
            unhappyboolean: $unhappyboolean
        }
        ')

echo "$JSON" | jq

Produces this output:

{
  "happystring": "Bob Ross",
  "unhappynumber1": "1942",
  "unhappyboolean": "true"
}

I know I can use tonumber to convert a string to a number in a simple filter. However, I cannot figure out how to convert a string to a boolean. And I'm having trouble reasoning how to do either when sourcing from shell vars and creating new json as output.

Desired output:

{
  "happystring": "Bob Ross",
  "unhappynumber1": 1942,
  "unhappyboolean": true
}

Would it be easier or more clear if I produced the json and stored it in a shell var in one step, and then performed the additional conversion in a second step?

like image 968
Balok Avatar asked Feb 21 '19 18:02

Balok


2 Answers

There's no need to convert variables to strings like --arg does only to convert them back, you can use --argjson and still input them separately but with types determined by the normal JSON rules:

happystring='"Bob Ross"'
unhappynumber1=1942
unhappyboolean=true

JSON=$(jq -n \
      --argjson happystring "$happystring" \
      --argjson unhappynumber1 "$unhappynumber1" \
      --argjson unhappyboolean "$unhappyboolean" \
      '
      {
          happystring: $happystring,
          unhappynumber1: $unhappynumber1,
          unhappyboolean: $unhappyboolean
      }
      ')

      echo "$JSON"

You could also mix --arg for strings and --argjson for everything else if you prefer not needing literal " quotes for the string arguments, as the note in the manual on shell quoting and the program text really applies to any arguments with characters you need to escape in your shell:

Note: it is important to mind the shell’s quoting rules. As a general rule it’s best to always quote (with single-quote characters) the jq program, as too many characters with special meaning to jq are also shell meta-characters. For example, jq "foo" will fail on most Unix shells because that will be the same as jq foo, which will generally fail because foo is not defined. When using the Windows command shell (cmd.exe) it’s best to use double quotes around your jq program when given on the command-line (instead of the -f program-file option), but then double-quotes in the jq program need backslash escaping.

like image 137
lossleader Avatar answered Oct 12 '22 01:10

lossleader


You can use test filter to do the check and return true/false. And I think you can just use the filters directly, no need to create a json and convert again.

happystring="Bob Ross"
unhappynumber1="1942"
unhappyboolean=true

JSON=$(jq -n \
        --arg happystring "$happystring" --arg unhappynumber1 "$unhappynumber1" \
        --arg unhappyboolean $unhappyboolean \
        '
        {
            happystring: $happystring,
            unhappynumber1: $unhappynumber1 | tonumber,
            unhappyboolean: $unhappyboolean | test("true")
        }
        ')

echo "$JSON" | jq

will give output as:

{
  "happystring": "Bob Ross",
  "unhappynumber1": 1942,
  "unhappyboolean": true
}
like image 24
Kamal Avatar answered Oct 12 '22 03:10

Kamal