Json – Escaping characters in bash (for JSON)

bashescapingjson

I'm using git, then posting the commit message and other bits as a JSON payload to a server.

Currently I have:

MSG=`git log -n 1 --format=oneline | grep -o ' .\+'`

which sets MSG to something like:

Calendar can't go back past today

then

curl -i -X POST \
  -H 'Accept: application/text' \
  -H 'Content-type: application/json' \
  -d "{'payload': {'message': '$MSG'}}" \
  'https://example.com'

My real JSON has another couple of fields.

This works fine, but of course when I have a commit message such as the one above with an apostrophe in it, the JSON is invalid.

How can I escape the characters required in bash? I'm not familiar with the language, so am not sure where to start. Replacing ' with \' would do the job at minimum I suspect.

Best Solution

Using Python:

This solution is not pure bash, but it's non-invasive and handles unicode.

json_escape () {
    printf '%s' "$1" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))'
}

Note that JSON is part of the standard python libraries and has been for a long time, so this is a pretty minimal python dependency.

Or using PHP:

json_escape () {
    printf '%s' "$1" | php -r 'echo json_encode(file_get_contents("php://stdin"));'
}

Use like so:

$ json_escape "ヤホー"
"\u30e4\u30db\u30fc"