Bash itself has no JSON support. Thus, to guarantee conformance, you need to use an external utility with JSON parsing and generation support built in. jq is one of these, and the below uses its built-in regex support:
jq --raw-input \
--arg date "$(date)" \
--arg osver "$(lsb_release -a)" \
'{"date": $date,
"osver": $osver,
"ip_info": [inputs |
capture("^[0-9]+: (?<ifname>[^[:space:]]+)[[:space:]]+inet (?<addr>[^[:space:]/]+)(/(?<masklen>[[:digit:]]+))?")
]
}' \
< <(ip -o addr list | grep 'inet ')
See this code in action on JQPlay.
If you can't install tools not built into your Linux distro, consider Python:
#!/bin/bash
# ^^^^ - important, not /bin/sh; this uses some bash-only syntax
py_code=$(cat <<'EOF'
import json, re, sys
content={'ip_info': []}
for k, v in [ arg.split('=', 1) for arg in sys.argv[2:] if '=' in arg ]:
content[k]=v
ip_re = re.compile(r'^[0-9]+:\s+(?P<ifname>\S+)\s+inet (?P<addr>[^/\s]+)(?:/(?P<masklen>\d+))?')
for line in open(sys.argv[1]).readlines():
m = ip_re.match(line)
if not m: raise "NOOOO"
content['ip_info'].append({
'ifname': m.groups('ifname'),
'addr': m.groups('addr'),
'masklen': m.groups('masklen'),
})
print json.dumps(content)
EOF
)
python -c "$py_code" \
<(ip -o addr list | grep 'inet ') \
"date=$(date)" "osver=$(lsb_release -a)"